#include "Joueur.h"

//#include "ADD.h"

// Classes
#include "Classe.h"
#include "Barde.h"
#include "Clerc.h"
#include "Druide.h"
#include "Guerrier.h"
#include "Mage.h"
#include "Paladin.h"
#include "Rodeur.h"
#include "Specialiste.h"
#include "Voleur.h"
#include "MetaClasse.h"

// Races
#include "Race.h"
#include "DemiElfe.h"
#include "DemiOgre.h"
#include "DemiOrque.h"
#include "Elfe.h"
#include "Gnome.h"
#include "Hobbit.h"
#include "Humain.h"
#include "Nain.h"
#include "MetaRace.h"

#include "lib.h"

#include "LireNomAbstrait.h"

#include "EcrireMartiale.h"
#include "LireMartiales.h"

#include "ATL.h"

#include "Parser.h"

#include <boost/assign/list_of.hpp>

#include <algorithm>
//#include <functional>

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace std;
using namespace boost::assign;
using namespace boost::lambda;

/******************************************************************************
 *
 * Définitions des attributs 'static'
 *
 *****************************************************************************/

const string Joueur::Aj_Force[30][6] =
  {
    {"$-5$", "$-4$" , "$0.5$"  , "$1.5$"  , "$1$" , "$0\\%$" }, // 1
    {"$-3$", "$-2$" , "$0.5$"  , "$2.5$"  , "$1$" , "$0\\%$" }, // 2
    {"$-3$", "$-1$" , "$2.5$"  , "$5$"    , "$2$" , "$0\\%$" }, // 3
    {"$-2$", "$-1$" , "$5$"    , "$12.5$" , "$3$" , "$0\\%$" }, // 4
    {"$-2$", "$-1$" , "$5$"    , "$12.5$" , "$3$" , "$0\\%$" }, // 5
    {"$-1$", "$0$"  , "$10$"   , "$27.5$" , "$4$" , "$0\\%$" }, // 6
    {"$-1$", "$0$"  , "$10$"   , "$27.5$" , "$4$" , "$0\\%$" }, // 7
    {"$0$" , "$0$"  , "$17.5$" , "$45$"   , "$5$" , "$1\\%$" }, // 8
    {"$0$" , "$0$"  , "$17.5$" , "$45$"   , "$5$" , "$1\\%$" }, // 9
    {"$0$" , "$0$"  , "$20$"   , "$57.5$" , "$6$" , "$2\\%$" }, // 10
    {"$0$" , "$0$"  , "$20$"   , "$57.5$" , "$6$" , "$2\\%$" }, // 11
    {"$0$" , "$0$"  , "$22.5$" , "$70$"   , "$7$" , "$4\\%$" }, // 12
    {"$0$" , "$0$"  , "$22.5$" , "$70$"   , "$7$" , "$4\\%$" }, // 13
    {"$0$" , "$0$"  , "$27.5$" , "$85$"   , "$8$" , "$7\\%$" }, // 14
    {"$0$" , "$0$"  , "$27.5$" , "$85$"   , "$8$" , "$7\\%$" }, // 15
    {"$0$" , "$+1$" , "$35$"   , "$97.5$" , "$9$" , "$10\\%$"}, // 16
    {"$+1$", "$+1$" , "$42.5$" , "$110$"  , "$10$", "$13\\%$"}, // 17
    {"$+1$", "$+2$" , "$55$"   , "$127.5$", "$11$", "$16\\%$"}, // 18
    {"$+3$", "$+7$" , "$242.5$", "$270$"  , "$16$", "$50\\%$"}, // 19
    {"$+3$", "$+8$" , "$267.5$", "$350$"  , "$17$", "$60\\%$"}, // 20
    {"$+4$", "$+9$" , "$317.5$", "$405$"  , "$17$", "$70\\%$"}, // 21
    {"$+4$", "$+10$", "$392.5$", "$485$"  , "$18$", "$80\\%$"}, // 22
    {"$+5$", "$+11$", "$467.5$", "$565$"  , "$18$", "$90\\%$"}, // 23
    {"$+6$", "$+12$", "$617.5$", "$770$"  , "$19$", "$95\\%$"}, // 24
    {"$+7$", "$+14$", "$767.5$", "$875$"  , "$19$", "$99\\%$"}, // 25
    {"$+1$", "$+3$" , "$67.5$" , "$140$"  , "$12$", "$20\\%$"}, // 18 01-50
    {"$+2$", "$+3$" , "$80$"   , "$152.5$", "$13$", "$25\\%$"}, // 18 51-75
    {"$+2$", "$+4$" , "$92.5$" , "$165$"  , "$14$", "$30\\%$"}, // 18 76-90
    {"$+2$", "$+5$" , "$117.5$", "$190$"  , "$15$", "$35\\%$"}, // 18 91-99
    {"$+3$", "$+6$" , "$167.5$", "$240$"  , "$16$", "$40\\%$"}  // 18 100
  };

const string Joueur::Aj_Dexterite[14][3] =
  {
    {"$-6$", "$-6$", "$+5$"}, // 1
    {"$-4$", "$-4$", "$+5$"}, // 2
    {"$-3$", "$-3$", "$+4$"}, // 3
    {"$-2$", "$-2$", "$+3$"}, // 4
    {"$-1$", "$-1$", "$+2$"}, // 5
    {"$0$" , "$0$" , "$+1$"}, // 6
    {"$0$" , "$0$" , "$0$" }, // 7-14
    {"$0$" , "$0$" , "$-1$"}, // 15
    {"$+1$", "$+1$", "$-2$"}, // 16
    {"$+2$", "$+2$", "$-3$"}, // 17
    {"$+2$", "$+2$", "$-4$"}, // 18
    {"$+3$", "$+3$", "$-4$"}, // 19-20
    {"$+4$", "$+4$", "$-5$"}, // 21-23
    {"$+5$", "$+5$", "$-6$"}, // 24-25
  };

const string Joueur::Aj_Const[25][5] =
  {
    {"$-3$"  , "$25\\%$" , "Néant"           , "$30\\%$" , "$-2$"}, // 1
    {"$-2$"  , "$30\\%$" , "Néant"           , "$35\\%$" , "$-1$"}, // 2
    {"$-2$"  , "$35\\%$" , "Néant"           , "$40\\%$" , "$0$" }, // 3
    {"$-1$"  , "$40\\%$" , "Néant"           , "$45\\%$" , "$0$" }, // 4
    {"$-1$"  , "$45\\%$" , "Néant"           , "$50\\%$" , "$0$" }, // 5
    {"$-1$"  , "$50\\%$" , "Néant"           , "$55\\%$" , "$0$" }, // 6
    {"$0$"   , "$55\\%$" , "Néant"           , "$60\\%$" , "$0$" }, // 7
    {"$0$"   , "$60\\%$" , "Néant"           , "$65\\%$" , "$0$" }, // 8
    {"$0$"   , "$65\\%$" , "Néant"           , "$70\\%$" , "$0$" }, // 9
    {"$0$"   , "$70\\%$" , "Néant"           , "$75\\%$" , "$0$" }, // 10
    {"$0$"   , "$75\\%$" , "Néant"           , "$80\\%$" , "$0$" }, // 11
    {"$0$"   , "$80\\%$" , "Néant"           , "$85\\%$" , "$0$" }, // 12
    {"$0$"   , "$85\\%$" , "Néant"           , "$90\\%$" , "$0$" }, // 13
    {"$0$"   , "$88\\%$" , "Néant"           , "$92\\%$" , "$0$" }, // 14
    {"$+1$"  , "$90\\%$" , "Néant"           , "$94\\%$" , "$0$" }, // 15
    {"$+2$"  , "$95\\%$" , "Néant"           , "$96\\%$" , "$0$" }, // 16
    {"$+2/3$", "$97\\%$" , "Néant"           , "$98\\%$" , "$0$" }, // 17
    {"$+2/4$", "$99\\%$" , "Néant"           , "$100\\%$", "$0$" }, // 18
    {"$+2/5$", "$99\\%$" , "Néant"           , "$100\\%$", "$+1$"}, // 19
    {"$+2/5$", "$99\\%$" , "$\\frac{1}{6}$~t", "$100\\%$", "$+1$"}, // 20
    {"$+2/6$", "$99\\%$" , "$\\frac{1}{5}$~t", "$100\\%$", "$+2$"}, // 21
    {"$+2/6$", "$99\\%$" , "$\\frac{1}{4}$~t", "$100\\%$", "$+2$"}, // 22
    {"$+2/6$", "$99\\%$" , "$\\frac{1}{3}$~t", "$100\\%$", "$+3$"}, // 23
    {"$+2/7$", "$99\\%$" , "$\\frac{1}{2}$~t", "$100\\%$", "$+3$"}, // 24
    {"$+2/7$", "$100\\%$", "1~t"             , "$100\\%$", "$+4$"}  // 25
  };

const string Joueur::Aj_Int[19][5] =
  {
    {"$0$"  , "$-$", "$-$"     , "$-$" , "$-$"}, // 1
    {"$1$"  , "$-$", "$-$"     , "$-$" , "$-$"}, // 2-8
    {"$2$"  , "$4$", "$35\\%$" , "$6$" , "$-$"}, // 9
    {"$2$"  , "$5$", "$40\\%$" , "$7$" , "$-$"}, // 10
    {"$2$"  , "$5$", "$45\\%$" , "$7$" , "$-$"}, // 11
    {"$3$"  , "$6$", "$50\\%$" , "$7$" , "$-$"}, // 12
    {"$3$"  , "$6$", "$55\\%$" , "$9$" , "$-$"}, // 13
    {"$4$"  , "$7$", "$60\\%$" , "$9$" , "$-$"}, // 14
    {"$4$"  , "$7$", "$65\\%$" , "$11$", "$-$"}, // 15
    {"$5$"  , "$8$", "$70\\%$" , "$11$", "$-$"}, // 16
    {"$6$"  , "$8$", "$75\\%$" , "$14$", "$-$"}, // 17
    {"$7$"  , "$9$", "$85\\%$" , "$18$", "$-$"}, // 18
    {"$8$"  , "$9$", "$95\\%$" , "Tous", "$1$"}, // 19
    {"$9$"  , "$9$", "$96\\%$" , "Tous", "$2$"}, // 20
    {"$10$" , "$9$", "$97\\%$" , "Tous", "$3$"}, // 21
    {"$11$" , "$9$", "$98\\%$" , "Tous", "$4$"}, // 22
    {"$12$" , "$9$", "$99\\%$" , "Tous", "$5$"}, // 23
    {"$15$" , "$9$", "$100\\%$", "Tous", "$6$"}, // 24
    {"$20$" , "$9$", "$100\\%$", "Tous", "$7$"}  // 29
  };

const string Joueur::Aj_Sagesse[24][4] =
  {
    {"$-6$", "$-$"   , "$80\\%$", "Néant"}, // 1
    {"$-4$", "$-$"   , "$60\\%$", "Néant"}, // 2
    {"$-3$", "$-$"   , "$50\\%$", "Néant"}, // 3
    {"$-2$", "$-$"   , "$45\\%$", "Néant"}, // 4
    {"$-1$", "$-$"   , "$40\\%$", "Néant"}, // 5
    {"$-1$", "$-$"   , "$35\\%$", "Néant"}, // 6
    {"$-1$", "$-$"   , "$30\\%$", "Néant"}, // 7
    {"$0$" , "$-$"   , "$25\\%$", "Néant"}, // 8
    {"$0$" , "$0$"   , "$20\\%$", "Néant"}, // 9
    {"$0$" , "$0$"   , "$15\\%$", "Néant"}, // 10
    {"$0$" , "$0$"   , "$10\\%$", "Néant"}, // 11
    {"$0$" , "$0$"   , "$5\\%$" , "Néant"}, // 12
    {"$0$" , "$1$"   , "$0\\%$" , "Néant"}, // 13-14
    {"$+1$", "$2$"   , "$0\\%$" , "Néant"}, // 15
    {"$+2$", "$2$"   , "$0\\%$" , "Néant"}, // 16
    {"$+3$", "$3$"   , "$0\\%$" , "Néant"}, // 17
    {"$+4$", "$4$"   , "$0\\%$" , "Néant"}, // 18
    {"$+4$", "$1, 3$", "$0\\%$" , ""     }, // 19
    {"$+4$", "$2, 4$", "$0\\%$" , ""     }, // 20
    {"$+4$", "$3, 5$", "$0\\%$" , ""     }, // 21
    {"$+4$", "$4, 5$", "$0\\%$" , ""     }, // 22
    {"$+4$", "$1, 6$", "$0\\%$" , ""     }, // 23
    {"$+4$", "$5, 6$", "$0\\%$" , ""     }, // 24
    {"$+4$", "$6, 7$", "$0\\%$" , ""     }  // 25
  };

const string Joueur::Aj_Charisme[24][3] =
  {
    {"$0$" , "$-8$" , "$-7$" }, // 1
    {"$1$" , "$-7$" , "$-6$" }, // 2
    {"$1$" , "$-6$" , "$-5$" }, // 3
    {"$2$" , "$-5$" , "$-4$" }, // 4
    {"$2$" , "$-4$" , "$-3$" }, // 5
    {"$2$" , "$-3$" , "$-2$" }, // 6
    {"$3$" , "$-2$" , "$-1$" }, // 7
    {"$3$" , "$-1$" , "$0$"  }, // 8
    {"$4$" , "$0$"  , "$0$"  }, // 9-11
    {"$5$" , "$0$"  , "$0$"  }, // 12
    {"$5$" , "$0$"  , "$+1$" }, // 13
    {"$6$" , "$+1$" , "$+2$" }, // 14
    {"$7$" , "$+3$" , "$+3$" }, // 15
    {"$8$" , "$+4$" , "$+5$" }, // 16
    {"$10$", "$+6$" , "$+6$" }, // 17
    {"$15$", "$+8$" , "$+7$" }, // 18
    {"$20$", "$+10$", "$+8$" }, // 19
    {"$25$", "$+12$", "$+9$" }, // 20
    {"$30$", "$+14$", "$+10$"}, // 21
    {"$35$", "$+16$", "$+11$"}, // 22
    {"$40$", "$+18$", "$+12$"}, // 23
    {"$45$", "$+20$", "$+13$"}, // 24
    {"$50$", "$+20$", "$+14$"}  // 25
  };

const vector< CapaciteRaciale > Joueur::Dons = list_of
  (CapaciteRaciale("Ambidextrie"            , 4))
  (CapaciteRaciale("Artiste"                , 4))
  (CapaciteRaciale("Bagout"                 , 4))
  (CapaciteRaciale("Belle voix"             , 5))
  (CapaciteRaciale("Brio musical"           , 4))
  (CapaciteRaciale("Chance"                 , 6))
  (CapaciteRaciale("Désarticulé"            , 4))
  (CapaciteRaciale("Empathie"               , 4))
  (CapaciteRaciale("Empathie animale"       , 4))
  (CapaciteRaciale("Goût développé"         , 4))
  (CapaciteRaciale("Grâce"                  , 4))
  (CapaciteRaciale("Guérison rapide"        , 6))
  (CapaciteRaciale("Imposture"              , 5))
  (CapaciteRaciale("Mémoire éidétique"      , 4))
  (CapaciteRaciale("Odorat développé"       , 6))
  (CapaciteRaciale("Ouïe développée"        , 5))
  (CapaciteRaciale("Prévision du temps"     , 4))
  (CapaciteRaciale("Résistance à la chaleur", 5))
  (CapaciteRaciale("Résistance au froid"    , 4))
  (CapaciteRaciale("Résistance au poison"   , 6))
  (CapaciteRaciale("Résistance immunitaire" , 5))
  (CapaciteRaciale("Science infuse"         , 4))
  (CapaciteRaciale("Sens de l'orientation"  , 5))
  (CapaciteRaciale("Sommeil léger"          , 5))
  (CapaciteRaciale("Toucher développé"      , 4))
  (CapaciteRaciale("Vigilance"              , 6))
  (CapaciteRaciale("Vision développée"      , 5));

const vector< CapaciteRaciale > Joueur::Desavantages = list_of
  (CapaciteRaciale("Allergies (modérées)"       ,  3))
  (CapaciteRaciale("Allergies (graves)"         ,  8))
  (CapaciteRaciale("Avidité"                    ,  7))
  (CapaciteRaciale("Daltonien"                  ,  3))
  (CapaciteRaciale("Ennemi puissant"            , 10))
  (CapaciteRaciale("Fanatisme"                  ,  8))
  (CapaciteRaciale("Fragile"                    ,  8))
  (CapaciteRaciale("Gaffeur"                    ,  6))
  (CapaciteRaciale("Honnêteté pathologique"     ,  8))
  (CapaciteRaciale("Lâcheté (modérée)"          ,  7))
  (CapaciteRaciale("Lâcheté (grave)"            , 15))
  (CapaciteRaciale("Maladroit (modéré)"         ,  4))
  (CapaciteRaciale("Maladroit (grave)"          ,  8))
  (CapaciteRaciale("Malchanceux"                ,  8))
  (CapaciteRaciale("Paresse"                    ,  7))
  (CapaciteRaciale("Pénible"                    ,  6))
  (CapaciteRaciale("Ph. araignées (modérée)"    ,  5))
  (CapaciteRaciale("Ph. araignées (grave)"      , 10))
  (CapaciteRaciale("Ph. eau (modérée)"          ,  6))
  (CapaciteRaciale("Ph. eau (grave)"            , 12))
  (CapaciteRaciale("Ph. espaces clos (modérée)" ,  5))
  (CapaciteRaciale("Ph. espaces clos (grave)"   , 11))
  (CapaciteRaciale("Ph. foule (modérée)"        ,  4))
  (CapaciteRaciale("Ph. foule (grave)"          , 10))
  (CapaciteRaciale("Ph. hauteurs (modérée)"     ,  5))
  (CapaciteRaciale("Ph. hauteurs (grave)"       , 10))
  (CapaciteRaciale("Ph. magie (modérée)"        ,  8))
  (CapaciteRaciale("Ph. magie (grave)"          , 14))
  (CapaciteRaciale("Ph. monstre (modérée)"      ,  4))
  (CapaciteRaciale("Ph. monstre (grave)"        ,  9))
  (CapaciteRaciale("Ph. morts-vivants (modérée)",  8))
  (CapaciteRaciale("Ph. morts-vivants (grave)"  , 14))
  (CapaciteRaciale("Ph. serpents (modérée)"     ,  5))
  (CapaciteRaciale("Ph. serpents (grave)"       , 10))
  (CapaciteRaciale("Ph. ténèbres (modérée)"     ,  5))
  (CapaciteRaciale("Ph. ténèbres (grave)"       , 11))
  (CapaciteRaciale("Sommeil lourd"              ,  7))
  (CapaciteRaciale("Susceptible"                ,  6));

const vector< NonMartiale > Joueur::CompetencesDiverses =
  // Générales - 36
  list_of
  ( NonMartiale( "Agriculture"          , 3, 7,   3, 255, Toutes ) )
  ( NonMartiale( "Allumage de feu"      , 2, 8,   3,   4, Toutes ) )
  ( NonMartiale( "Brassage"             , 3, 8,   3, 255, Toutes ) )
  ( NonMartiale( "Chant"                , 2, 5,   5, 255, Toutes ) )
  ( NonMartiale( "Charpenterie"         , 3, 7,   0,   3, Toutes ) )
  ( NonMartiale( "Cordonnerie"          , 3, 7,   1,   3, Toutes ) )
  ( NonMartiale( "Cuisine"              , 3, 7,   3, 255, Toutes ) )
  ( NonMartiale( "Danse"                , 2, 6,   1,   5, Toutes ) )
  ( NonMartiale( "Dressage d'animaux"   , 4, 5,   4,   5, Toutes ) )
  ( NonMartiale( "Equitation"           , 2, 8,   4,   1, Toutes ) )
  ( NonMartiale( "Equitation en vol"    , 4, 5,   4,   1, Toutes ) )
  ( NonMartiale( "Etiquette"            , 2, 8,   5,   4, Toutes ) )
  ( NonMartiale( "Expertise maritime"   , 3, 8,   1,   4, Toutes ) )
  ( NonMartiale( "Forge"                , 4, 6,   0,   3, Toutes ) )
  ( NonMartiale( "Héraldique"           , 2, 8,   3, 255, Toutes ) )
  ( NonMartiale( "Ingénierie"           , 4, 5,   3,   4, Toutes ) )
  ( NonMartiale( "Instrument de musique", 2, 7,   5, 255, Toutes ) )
  ( NonMartiale( "Jeu"                  , 2, 5,   4,   3, Toutes ) )
  ( NonMartiale( "Langues modernes"     , 2, 9,   3, 255, Toutes ) )
  ( NonMartiale( "Maçonnerie"           , 4, 5,   0,   3, Toutes ) )
  ( NonMartiale( "Maîtrise des animaux" , 3, 7,   4, 255, Toutes ) )
  ( NonMartiale( "Maroquinerie"         , 3, 7,   3,   1, Toutes ) )
  ( NonMartiale( "Météorologie"         , 2, 7,   4, 255, Toutes ) )
  ( NonMartiale( "Mine"                 , 5, 5,   4,   0, Toutes ) )
  ( NonMartiale( "Natation"             , 2, 9,   0, 255, Toutes ) )
  ( NonMartiale( "Navigation"           , 3, 6,   3,   4, Toutes ) )
  ( NonMartiale( "Orientation"          , 3, 7,   3,   4, Toutes ) )
  ( NonMartiale( "Pêche"                , 3, 6,   4,   3, Toutes ) )
  ( NonMartiale( "Peinture"             , 3, 7,   1,   4, Toutes ) )
  ( NonMartiale( "Petits bateaux"       , 2, 6,   0,   3, Toutes ) )
  ( NonMartiale( "Plongée"              , 2, 5,   1,   2, Toutes ) )
  ( NonMartiale( "Poterie"              , 3, 7,   1, 255, Toutes ) )
  ( NonMartiale( "Sculpture"            , 2, 5,   1,   4, Toutes ) )
  ( NonMartiale( "Sixième sens"         , 2, 7,   4, 255, Toutes ) )
  ( NonMartiale( "Tailleur"             , 3, 7,   1,   3, Toutes ) )
  ( NonMartiale( "Utilis. de cordes"    , 2, 8,   1,   4, Toutes ) )
  // Combattants - 13
  ( NonMartiale( "Alpinisme"            , 4, 7,   0,   4, Combattants ) )
  ( NonMartiale( "Armurier"             , 5, 5,   3,   0, Combattants ) )
  //( NonMartiale( "Bon équilibre"        , 7,   1, 255, Combattants ) )
  //( NonMartiale( "Camouflage"           , 5,   3, 255, Combattants ) )
  ( NonMartiale( "Chasse"               , 2, 7,   4, 255, Combattants ) )
  ( NonMartiale( "Combat aveugle"       , 4, 6,   1,   4, Combattants ) )
  //( NonMartiale( "Commandement"         , 6,   5, 255, Combattants ) )
  ( NonMartiale( "Conduite de char"     , 4, 5,   1,   4, Combattants ) )
  ( NonMartiale( "Conn. des animaux"    , 3, 7,   3,   4, Combattants ) )
  //( NonMartiale( "Coup de pied arrière" , 0, 255, 255, Combattants ) )
  //( NonMartiale( "Coup de pied sauté"   , 5,   0, 255, Combattants ) )
  //( NonMartiale( "Coup redoutable"      , 0, 255, 255, Combattants ) )
  ( NonMartiale( "Course"               , 2, 5,   0,   2, Combattants ) )
  //( NonMartiale( "Embuscade"            , 5,   3, 255, Combattants ) )
  ( NonMartiale( "Endurance"            , 2, 3,   2, 255, Combattants ) )
  ( NonMartiale( "Fab. d'arc et flèches", 5, 6,   3,   1, Combattants ) )
  ( NonMartiale( "Forge d'armes"        , 5, 5,   3,   1, Combattants ) )
  //( NonMartiale( "Oeil sûr"             , 0, 255, 255, Combattants ) )
  //( NonMartiale( "Parade de proj."      , 0, 255, 255, Combattants ) )
  ( NonMartiale( "Pistage"              , 4, 7,   4, 255, Combattants ) )
  ( NonMartiale( "Pose de collets"      , 4, 6,   1,   4, Combattants ) )
  //( NonMartiale( "Rapidité"             , 3,   1, 255, Combattants ) )
  //( NonMartiale( "Rétabliss. instant."  , 7,   1, 255, Combattants ) )
  //( NonMartiale( "Saut"                 , 5,   1, 255, Combattants ) )
  ( NonMartiale( "Survie"               , 3, 6,   3,    4, Combattants ) )
  //( NonMartiale( "Volonté de fer"       , 3,   4, 255, Combattants ) )
  // Magiciens - 10
  ( NonMartiale( "Astrologie"           , 3, 5,   3,   4, Magiciens ) )
  ( NonMartiale( "Astronomie"           , 2, 7,   3, 255, Magiciens ) )
  ( NonMartiale( "Conn. des sorts"      , 3, 7,   3, 255, Magiciens ) )
  ( NonMartiale( "Cryptographie"        , 3, 6,   3,   4, Magiciens ) )
  ( NonMartiale( "Herboristerie"        , 3, 6,   3,   4, Magiciens ) )
  ( NonMartiale( "Histoire ancienne"    , 3, 6,   3,   4, Magiciens ) )
  ( NonMartiale( "Joaillerie"           , 3, 6,   1, 255, Magiciens ) )
  ( NonMartiale( "Langues mortes"       , 4, 5,   3, 255, Magiciens ) )
  ( NonMartiale( "Lecture-écriture"     , 2, 8,   3, 255, Magiciens ) )
  ( NonMartiale( "Religion"             , 2, 6,   4, 255, Magiciens ) )
  // Prêtres - 9
  ( NonMartiale( "Astrologie"           , 3, 5,   3,   4, Pretres ) )
  ( NonMartiale( "Conn. des sorts"      , 3, 7,   3, 255, Pretres ) )
  //( NonMartiale( "Coup de pied arrière" , 0, 255, 255, Pretres ) )
  //( NonMartiale( "Coup redoutable"      , 0, 255, 255, Pretres ) )
  ( NonMartiale( "Herboristerie"        , 3, 6,   3,   4, Pretres ) )
  ( NonMartiale( "Histoire ancienne"    , 3, 6,   3,   4, Pretres ) )
  ( NonMartiale( "Histoire locale"      , 2, 8,   3,   5, Pretres ) )
  ( NonMartiale( "Langues mortes"       , 4, 5,   3, 255, Pretres ) )
  ( NonMartiale( "Lecture-écriture"     , 2, 8,   3, 255, Pretres ) )
  //( NonMartiale( "Parade de proj."      , 0, 255, 255, Pretres ) )
  ( NonMartiale( "Premiers secours"     , 4, 5,   5,   4, Pretres ) )
  ( NonMartiale( "Religion"             , 2, 6,   4, 255, Pretres ) )
  //( NonMartiale( "Rétabliss. instant."  , 7,   1, 255, Pretres ) )
  //( NonMartiale( "Volonté de fer"       , 3,   4, 255, Pretres ) )
  // Roublards - 16
  ( NonMartiale( "Acrobatie"            , 3, 7,   1,   0, Roublards ) )
  //( NonMartiale( "Bon équilibre"        , 7,   1, 255, Roublards ) )
  //( NonMartiale( "Camouflage"           , 5,   3, 255, Roublards ) )
  ( NonMartiale( "Combat aveugle"       , 4, 6,   1,   4, Roublards ) )
  ( NonMartiale( "Contrefaçon"          , 3, 5,   1,   4, Roublards ) )
  //( NonMartiale( "Coup de pied arrière" , 0, 255, 255, Roublards ) )
  //( NonMartiale( "Coup redoutable"      , 0, 255, 255, Roublards ) )
  ( NonMartiale( "Cryptographie"        , 3, 6,   3,   4, Roublards ) )
  ( NonMartiale( "Déguisement"          , 4, 5,   5,   4, Roublards ) )
  //( NonMartiale( "Embuscade"            , 5,   3, 255, Roublards ) )
  ( NonMartiale( "Evaluation"           , 2, 8,   3,   4, Roublards ) )
  ( NonMartiale( "Funambulisme"         , 3, 5,   1, 255, Roublards ) )
  ( NonMartiale( "Histoire ancienne"    , 3, 6,   3,   4, Roublards ) )
  ( NonMartiale( "Histoire locale"      , 2, 8,   3,   5, Roublards ) )
  ( NonMartiale( "Joaillerie"           , 3, 6,   1, 255, Roublards ) )
  ( NonMartiale( "Jonglerie"            , 3, 7,   1, 255, Roublards ) )
  ( NonMartiale( "Lancer"               , 2, 8,   1,   0, Roublards ) )
  ( NonMartiale( "Lire sur les lèvres"  , 3, 7,   3,   4, Roublards ) )
  //( NonMartiale( "Oeil sûr"             , 0, 255, 255, Roublards ) )
  //( NonMartiale( "Parade de proj."      , 0, 255, 255, Roublards ) )
  ( NonMartiale( "Pose de collets"      , 3, 6,   1,   4, Roublards ) )
  //( NonMartiale( "Rapidité"             , 3,   1, 255, Roublards ) )
  //( NonMartiale( "Rétabliss. instant."  , 7,   1, 255, Roublards ) )
  ( NonMartiale( "Saut"                 , 2, 8,   1,   0, Roublards ) )
  //( NonMartiale( "Saut (mart.)"         , 5,   1, 255, Roublards ) )
  ( NonMartiale( "Ventriloquie"         , 4, 5,   3,   5, Roublards ) );

const string Joueur::CategoriesCompetences[5] = {"Générales", "Combattants",
						 "Magiciens", "Prêtres",
						 "Roublards"};

const map<string, unsigned> Joueur::GererClasses = map_list_of
  ("Guerrier"   , 0)
  ("Paladin"    , 0)
  ("Rôdeur"     , 0)
  ("Mage"       , 1)
  ("Spécialiste", 1)
  ("Clerc"      , 2)
  ("Druide"     , 3)
  ("Voleur"     , 4)
  ("Barde"      , 0);

const vector<unsigned>* Joueur::CompMartialesParClasse[5] =
  {
    0, &CompMarMage, &CompMarClerc, &CompMarDruide, &CompMarVoleur
  };

const vector<unsigned> Joueur::CompMarClerc = list_of
  (6)(46)(47)(48)(49)(50)(52)(53)
  (55)(133)(134)(137)(138)(141)
  (142)(143)(154)(155)(156)(157)
  (162)(165)(166)(167)(168)(169)
  (170)(180)(183)(191)(194)(197)
  (198)(203)(204);

const vector<unsigned> Joueur::CompMarMage = list_of
  (58)(59)(60)(62)(63)(165)(126)
  (181)(159)(160)(161)(162);

const vector<unsigned> Joueur::CompMarDruide = list_of
  (137)(173)(126)(62)(63)(181)
  (165);

const vector<unsigned> Joueur::CompMarVoleur = list_of
  (137)(62)(63)(126)(0)(58)(59)
  (60)(61)(192)(18)(181)(97)(98)
  (91)(165);

DebugLevelType Joueur::fonction_elementaire_xml( BLANK );
DebugLevelType Joueur::fonction_recuperation_xml( BLANK );
DebugLevelType Joueur::fonction_tex( BLANK );
DebugLevelType Joueur::interne( BLANK );

bool Joueur::niveauxLus( false );

const vector< string > Joueur::NomsNiveaux =
  list_of( "Joueur::interne" )( "Joueur::fonction_elementaire_xml" )
  ( "Joueur::fonction_recuperation_xml" )( "Joueur::fonction_tex" );

bool Joueur::armesLues( false );

/**************************************************************************//**
 *
 * Le constructeur par défaut fait appel au chargement d'un Joueur depuis
 * un fichier .xml\n
 *
 * Le nom du fichier doit être entré. Ce nom est ensuite vérifié et on
 * appelle ensuite une instance de Parser qui extrait du fichier
 * l'information utile.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC permet d'afficher le message de début et de fin
 *
 ******************************************************************************/
Joueur::Joueur()
  : ADDObjetBase( "Joueur" ), TAc0(20), PP(0), nb_classes(1), CA(10),
    libere_mem( true )
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::Joueur -> début" << endmsg;

  if ( ! niveauxLus )
    {
      lireNiveaux( this, NomsNiveaux );
      niveauxLus = true;
    }



  if( ! armesLues )
    {
      LireArmesXML = UniqueLireMartiales::instance();
      if ( LireArmesXML == 0 ||
	   ! LireArmesXML -> init() )
	{
	  error() << "Impossible de récupérer la liste d'armes" << endmsg;
	  exit( 1 );
	}
      armesLues = true;
    }

  /*
   * J_race et J_classe sont alloué dynamiquement, il faudra donc libérer
   * la mémoire
   */

  string poubelle, nom_fichier;
  ifstream entree;
  bool pb_ouverture;
  do
    {
      blank() << "Entrer le nom du fichier à ouvrir : " << endaff;
      getline(cin, nom_fichier);
      nom_fichier = "XML/" + nom_fichier + ".xml";
      entree.open(nom_fichier.c_str());
      pb_ouverture = entree.fail();
      if (pb_ouverture)
	{
	  warning() << "Vérifier le nom du fichier : " << nom_fichier
		    << " invalide." << endmsg;
	  cin.clear();
	  getline(cin, poubelle);
	  entree.clear();
	}
    }
  while( pb_ouverture );

  Parser parseur( nom_fichier );

  blank() << "Lecture du fichier " << nom_fichier << " en cours" << endmsg;

  StatusCode sc( parseur.chargerFichier() );

  if ( ! sc )
    {
      error() << sc.message() << endmsg;
      exit( 1 );
    }

  sc = parseur.lireDocument();

  if ( ! sc )
    {
      error() << sc.message() << endmsg;
      
      func() << "Joueur::Joueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit( 1 );
    }

  map< string, string > infos;

  sc = parseur.getInformations( infos );

  if ( ! sc )
    {
      error() << sc.message() << endmsg;
      
      func() << "Joueur::Joueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit( 1 );
    }

  construitJoueur( &infos );

  func() << "Joueur::Joueur -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/***************************************************************************//**
 *
 * Ce constructeur sert lors de la création d'un nouveau Joueur. Dans
 * ce cas la Classe et la Race sont déterminés avant. Ce constructeur
 * est utilisé dans le cas du mode console ou avec l'interface
 * graphique.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC permet d'afficher les message de début et de fin.
 * \e LFUNC contrôle de la copie du script de création du personnage.
 *
 * @param[in] classe pointeur sur une classe déjà existante (qui sera
 * la première classe, attention si jumelage).
 * @param[in] race pointeur sur une race existance.
 * @param[in] nom est le nom du personnage.
 *
 *****************************************************************************/
Joueur::Joueur(Classe* classe, Race* race, const string& nom)
  : ADDObjetBase( "Joueur" ), J_race(race), TAc0(20), PP(0), nb_classes(1),
    CA(10)
{
  if ( ! niveauxLus )
    {
      lireNiveaux( this, NomsNiveaux );
      niveauxLus = true;
    }

  if( ! armesLues )
    {
      LireArmesXML = UniqueLireMartiales::instance();
      if ( LireArmesXML == 0 ||
	   ! LireArmesXML -> init() )
	{
	  error() << "Impossible de récupérer la liste d'armes" << endmsg;
	  exit( 1 );
	}
      armesLues = true;
    }

  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::Joueur -> début" << endmsg;

  Nom = nom;
  libere_mem = false;
  J_classe.push_back(classe);
  TM_switch = Non;

  const vector<TypeClasse>* tmpTC;
  tmpTC = classe -> tc();

  J_CompAccess.assign(tmpTC -> begin(), tmpTC -> end());

  ifstream script_entree;
  script_entree.open("Joueur0/Creation.sh");
  ofstream script_sortie;
  script_sortie.open("tmp.sh");
  string ligne;
  size_t loc;

  while ( ! script_entree.eof() )
    {
      getline(script_entree, ligne);
      loc = ligne.find("@", 0);
      if (loc != string::npos)
  	ligne.replace(loc, 1, convertNom());
      lfunc() << ligne << endmsg;
      script_sortie << ligne << endl;
    }

  script_entree.close();
  script_sortie.close();

  TAc0 = J_classe[0] -> calculeNombres();

  func() << "Joueur::Joueur -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/***************************************************************************//**
 * Constructeur qui permet de s'affranchir du pseudo-parseur
 * interne. On lit les informations depuis un fichier XML (avec
 * Parser ou le parseur natif Qt) et on construit le Joueur à partir
 * de la map tag - info.\n
 *
 * Ici on a déjà lu et chargé les informations contenues dans le
 * fichier xml désiré et on va dirictement construire le Joueur. La
 * totalité du boulot est effectuée par construitJoueur.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC début et fin du bloc du constructeur.
 *
 * @param[in] infoXML pointeur sur la table de correspondance balise -
 * information, obtenue comme résultat de la lecture du fichier
 * chargé.
 ******************************************************************************/
Joueur::Joueur( map< string, string >* infoXML )
  : ADDObjetBase( "Joueur" ), TAc0(20), PP(0), nb_classes(1), CA(10),
    libere_mem( true )
{
  if ( ! niveauxLus )
    {
      lireNiveaux( this, NomsNiveaux );
      niveauxLus = true;
    }

  if( ! armesLues )
    {
      LireArmesXML = UniqueLireMartiales::instance();
      if ( LireArmesXML == 0 ||
	   ! LireArmesXML -> init() )
	{
	  error() << "Impossible de récupérer la liste d'armes" << endmsg;
	  exit( 1 );
	}
      armesLues = true;
    }

  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur -> début" << endmsg;
 
  construitJoueur( infoXML );

  func() << "Joueur -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/***************************************************************************//**
 * Constructeur qui permet d'initialiser un Joueur depuis une instance
 * de Parser. Le fichier XML a donc déjà été lu. On vérifie alors la
 * syntaxe, on construit le conteneur balise - info et on appelle
 * construitJoueur.
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC permet d'afficher les message de début et de fin.
 *
 * @param[in] parser pointeur sur l'instance de Parser qui a lu le
 * fichier voulu.
 ***************************************************************************/
Joueur::Joueur( Parser const* parser )
  : ADDObjetBase( "Joueur" )
{
  if ( ! niveauxLus )
    {
      lireNiveaux( this, NomsNiveaux );
      niveauxLus = true;
    }

  if( ! armesLues )
    {
      LireArmesXML = UniqueLireMartiales::instance();
      if ( LireArmesXML == 0 ||
	   ! LireArmesXML -> init() )
	{
	  error() << "Impossible de récupérer la liste d'armes" << endmsg;
	  exit( 1 );
	}
      armesLues = true;
    }

  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur -> début" << endmsg;
  
  // Faire appel à premierEnfant -> vérifier que c'est bon
  // Ensuite on lit les champs 
  const ElementDOM *parent, *enfant;
  parent = parser -> premierEnfant();

  StatusCode sc( verifieBalise( parent, "Joueur" ) );
  if ( ! sc )
    {
      error() << sc.message() << endmsg;
      func() << "Joueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }

  enfant = parser -> premierEnfant( parent );
  faireVerificationBalise( enfant, "Nom" );

  map< string, string > infoLues;

  infoLues[ "Nom" ] = enfant -> donnees();

  parent = parser -> prochainFrere( enfant );
  faireVerificationBalise( enfant, "Info_Raciales" );

  enfant = parser -> premierEnfant( parent );
  faireVerificationBalise( enfant, "Race" );

  infoLues[ "Race" ] = enfant -> donnees();

  enfant = parser -> prochainFrere( enfant );
  faireVerificationBalise( enfant, "Capacites" );

  infoLues[ "Capacites" ] = enfant -> donnees();

  parent = parser -> prochainFrere( parent );
  faireVerificationBalise( enfant, "Traits" );

  infoLues[ "Traits" ] = parent -> donnees();

  parent = parser -> prochainFrere( parent );
  faireVerificationBalise( parent, "Info_Classes" );

  enfant = parser -> premierEnfant( parent );
  faireVerificationBalise( enfant, "Multi" );

  infoLues[ "Multi" ] = enfant -> donnees();

  enfant = parser -> premierEnfant( parent );
  faireVerificationBalise( enfant, "PP" );

  infoLues[ "PP" ] = enfant -> donnees();

  enfant = parser -> premierEnfant( parent );
  faireVerificationBalise( enfant, "Acces" );

  infoLues[ "Acces" ] = enfant -> donnees();

  enfant = parser -> prochainFrere( enfant );
  string ajout("");
  do
    {
      faireVerificationBalise( enfant, "Info_Classe" );
      lireClasse( enfant, ajout, parser, infoLues );
      ajout += '+';
      enfant = parser -> prochainFrere( enfant );
    }
  while ( enfant != 0 );

  enfant = parser -> premierEnfant( parent );
  faireVerificationBalise( enfant, "Dons" );

  infoLues[ "Dons" ] = enfant -> donnees();

  enfant = parser -> premierEnfant( parent );
  faireVerificationBalise( enfant, "Desavantages" );

  infoLues[ "Desavantages" ] = enfant -> donnees();

  enfant = parser -> premierEnfant( parent );
  faireVerificationBalise( enfant, "Non-martiales" );

  infoLues[ "Non-martiales" ] = enfant -> donnees();

  enfant = parser -> premierEnfant( parent );
  faireVerificationBalise( enfant, "Martiales" );

  infoLues[ "Martiales" ] = enfant -> donnees();

  construitJoueur( &infoLues );

  func() << "Joueur -> fin" << endmsg;
  /*Debug::*/depileNiveau();

}

/**************************************************************************//**
 *
 * Le destructeur libère au besoin la mémoire allouée dynamiquement.
 *
 *****************************************************************************/
Joueur::~Joueur()
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::~Joueur -> début" << endmsg;
  
  if ( libere_mem )
    {
      delete J_race;
      debug() << "Race libérée              [ OK ]" << endmsg;
      while ( ! J_classe.empty() )
	{
	  delete J_classe.back();
	  J_classe.pop_back();
	  debug() << "Classe libérée            [ OK ]" << endmsg;
	}
    }
  
  func() << "Joueur::~Joueur -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}


/**************************************************************************//**
 *
 * Effectue l'affichage des informations sur le Joueur. Affiche le
 * nom, puis la race, et enfin les informations sur les différentes
 * classes.
 *
 * @param[in] os flux de sortie utilisé, par défaut blank() est
 * utilisé.
 *
 *****************************************************************************/
void Joueur::information( ostream& os )
{
  os << Nom << endmsg;
  J_race -> afficheInfo( os );
  for (unsigned i(0); i < nb_classes; i++)
    J_classe[i] -> afficheStats( J_race -> type(), Traits, os );
}

/**************************************************************************//**
 *
 * Effectue l'affichage des informations sur le Joueur. Affiche le
 * nom, puis la race, et enfin les informations sur les différentes
 * classes.
 *
 * @param[in] flot instance de FLotMessage de sortie utilisé, par
 * défaut blank() est utilisé.
 *
 *****************************************************************************/
void Joueur::information( FlotMessage& flot )
{
  flot << Nom << endmsg;
  J_race -> afficheInfo( flot );
  for (unsigned i(0); i < nb_classes; i++)
    J_classe[i] -> afficheStats( J_race -> type(), Traits, flot );
}

/***************************************************************************//**
 *
 * Méthode générique pour demander le nom d'un fichier. L'extension est
 * gérée par la fonction d'appel à demanderNom().
 *
 ******************************************************************************/
string Joueur::demanderNom() const
{
  string ret;
  blank() << "Entrer le nom du fichier (sans extension) : " << endaff;
  getline(cin, ret);
  blank() << endmsg;
  return ret;
}

/***************************************************************************//**
 *
 * Sauve les données du Joueur dans un fichier XML. On ouvre tout
 * d'abord un fichier XML (on vérifie que l'on peut y écrire) puis on
 * récupère et écrit toutes les informations utiles.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les messages de début et de fin de méthode, ainsi
 * que le contrôle des différentes phases du processus.\n
 * \e LFUNC affiche quelle classe vient d'être écrite.\n
 *
 * FUNC  permet d'afficher l'état d'avancement de l'écriture
 *
 ******************************************************************************/
void Joueur::ecrireXml() const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::ecrireXml -> début" << endmsg;

  string nom_fichier, poubelle;
  ofstream sortie;
  bool test;
  getline(cin, poubelle);
  do
    {
      nom_fichier = demanderNom();
      nom_fichier = "XML/" + nom_fichier + ".xml";
      sortie.open(nom_fichier.c_str());
      test = sortie.fail();
      if (test)
	{
	  warning() << "Vérifier le nom du fichier : " << nom_fichier
		    << endmsg;
	  cin.clear();
	  sortie.clear();
          getline(cin, poubelle);
	}
    }
  while(test);

  // Définitions des foncteurs de sortie
  EcrireElementConteneur< unsigned, ostream >   sortieUInt( &sortie );
  EcrireElementConteneur< TypeClasse, ostream > sortieTC( &sortie );
  EcrireElementConteneur< Sort, ostream >       sortieSort( &sortie );

  func() << "Fichier ouvert" << endmsg;
  sortie << "<Joueur>" << endl;
  sortie << "  <Nom> " << Nom << " </Nom>" <<endl;
  sortie << "  <Info_Raciales>" << endl;
  sortie << "    <Race> " << J_race -> type() << " </Race>" << endl;
  sortie << "    <Capacites> ";
  for_each( J_race -> adresseCapacites() -> begin(),
	    J_race -> adresseCapacites() -> end(),
	    sortieUInt );
  sortie << "</Capacites>" << endl;
  sortie << "  </Info_Raciales>" << endl;
  func() << "Race écrite" << endmsg;
  sortie << "  <Traits> ";
  unsigned taille, i;
  for (i = 0; i< 7; i++)
    sortie << Traits[ i ] << ' ';
    //sortie << J_classe[0] -> trait(i) << ' ';
  sortie << "</Traits>" << endl;
  func() << "Traits OK" << endmsg;
  sortie << "  <Info_Classes>" << endl;
  sortie << "    <Multi> " << nb_classes << " </Multi>" << endl;
  sortie << "    <PP> " << PP << " </PP>" << endl;
  sortie << "      <Acces> ";
  for_each( J_CompAccess.begin(), J_CompAccess.end(), sortieTC );
  sortie << "</Acces>" << endl;
  func() << "On commence à écrire les classes" << endmsg;
  for (i = 0; i < nb_classes; i++)
    {
      sortie << "      <Info_Classe>" << endl;
      sortie << "        <Classe> " << J_classe[i] -> classe()
	     << " </Classe>" << endl;
      sortie << "        <PV> " << J_classe[i] -> pv() << " </PV>" << endl;
      sortie << "        <XP> " << J_classe[i] -> xp() << " </XP>" << endl;
      sortie << "        <Competences> ";
      debug() << "Classe, PV et XP écrits" << endmsg;
      for_each( J_classe[i] -> competences( taille ) -> begin(),
		J_classe[i] -> competences( taille ) -> end(),
		sortieUInt );
      sortie << "</Competences>" << endl;
      debug() << "Compétences de classe écrites" << endmsg;
      sortie << "        <Sorts> ";
      EcrireElementConteneur< Sort, ostream > sortieSort( &sortie );
      for_each(  J_classe[i] -> adresseSorts() -> begin(),
      		 J_classe[i] -> adresseSorts() -> end(),
      		 sortieSort );
      sortie << "</Sorts>" << endl;
      debug() << "Sorts écrits" << endmsg;
      sortie << "     </Info_Classe>" << endl;
      lfunc() << "Classe " << i << " écrite" << endmsg;
    }
  func() << "Classe(s) écrite(s)" << endmsg;
  sortie << "  </Info_Classes>" << endl;
  sortie << " <Dons> ";
  for_each( J_Dons.begin(), J_Dons.end(), sortieUInt );
  sortie << "</Dons>" << endl;
  sortie << " <Desavantages> ";
  for_each( J_Desavantages.begin(), J_Desavantages.end(), sortieUInt );
  sortie << "</Desavantages>" << endl;
  sortie << " <Non-martiales> ";
  for_each( J_CompDiv.begin(), J_CompDiv.end(), sortieUInt );
  sortie << "</Non-martiales>" << endl;
  sortie << " <Martiales> ";
  for_each( J_Martiales.begin(), J_Martiales.end(), sortieUInt );
  sortie << "</Martiales>" << endl;
  sortie << "</Joueur>" << endl;
  sortie.close();
  func() << "Fichier " << nom_fichier << " sauvé" << endmsg;

  func() << "Joueur::ecrireXml -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/***************************************************************************//**
 *
 * Fixe le nombre de pp du Joueur. Lors de la création, le
 * modificateur dû à l'intelligence est appliqué.
 *
 * @param[in] pps nombre de PP.
 * @param[in] creation \e true s'il s'agit de la création du PJ, \e
 * false sinon (valeur par défaut).
 *
 ******************************************************************************/
void Joueur::setPP(const unsigned& pps, const bool& creation)
{
  PP = pps;
  if ( creation )
    modificateurPP();
}

/***************************************************************************//**
 *
 * Fixe les traits du joueur.
 *
 * @param[in] traits conteuneur des traits.
 *
 ******************************************************************************/
void Joueur::setTraits( const vector< unsigned >& traits )
{
  Traits.assign( traits.begin(), traits.end() );
}

/***************************************************************************//**
 *
 * Permet de déterminer les dons du PJ, d'après une liste déjà
 * établie. Est utilisé typiquement lorsque le PJ est lu depuis un
 * fichier XML.
 *
 * @param[in] vec conteneur des dons.
 *
 ******************************************************************************/
void Joueur::setDons(const vector<unsigned>& vec)
{
  J_Dons.assign( vec.begin(), vec.end() );
}

/***************************************************************************//**
 *
 * Permet de déterminer les désavantages du PJ, d'après une liste déjà
 * établie. Est utilisé typiquement lorsque le PJ est lu depuis un
 * fichier XML.
 *
 * @param[in] vec conteneur des désavantages.
 *
 ******************************************************************************/
void Joueur::setDesavantages(const vector<unsigned>& vec)
{
  J_Desavantages.assign( vec.begin(), vec.end() );
}

/***************************************************************************//**
 *
 * Permet de déterminer les compétences diverses du PJ, d'après une
 * liste déjà établie. Est utilisé typiquement lorsque le PJ est lu
 * depuis un fichier XML.
 *
 * @param[in] vec conteneur des compétences diverses (avec la
 * structure Compétence - Valeur).
 *
 ******************************************************************************/
void Joueur::setDiverses(const vector<unsigned>& vec)
{
  J_CompDiv.assign( vec.begin(), vec.end() );
}

/***************************************************************************//**
 *
 * Permet de déterminer les compétences martiales du PJ, d'après une
 * liste déjà établie. Est utilisé typiquement lorsque le PJ est lu
 * depuis un fichier XML.
 *
 * @param[in] vec conteneur des compétences martiales
 *
 ******************************************************************************/
void Joueur::setMartiales(const vector<unsigned>& vec)
{
  J_Martiales.assign( vec.begin(), vec.end() );

  if ( J_Martiales.size() % 2 == 1 )
    warning() << "Attention, le nombre de compétence martiales n'est pas correct"
	      << endmsg;
}

/***************************************************************************//**
 *
 * Permet de déterminer les accès aux compétences diverses du PJ,
 * d'après une liste déjà établie. Est utilisé typiquement lorsque le
 * PJ est lu depuis un fichier XML.
 *
 * @param[in] vec conteneur des accès
 *
 ******************************************************************************/
void Joueur::setAcces(const vector<unsigned>& vec)
{
  unsigned nbr( vec.size() ), i;

  J_CompAccess.clear();

  for ( i = 0; i < nbr; i++ )
    J_CompAccess.push_back( static_cast< TypeClasse >( vec[i] ) );
}

/***************************************************************************//**
 *
 * Permet d'ajouter de nouvelles compétences diverses à la liste déjà
 * établie.
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les messages de début et de fin de méthode.\n
 *
 * @param[in] aAjouter conteneur des compétences diverses (avec la
 * structure Compétence - Valeur).
 * 
 ******************************************************************************/
void Joueur::ajouterDiverses(const vector<unsigned>& aAjouter)
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::ajouterDiverses -> début" << endmsg;

  vector<unsigned> nouvelles;
  gererDiverses( aAjouter, nouvelles );

  J_CompDiv.insert( J_CompDiv.end(), nouvelles.begin(), nouvelles.end() );

  func() <<  "Joueur::ajouterDiverses -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/***************************************************************************//**
 *
 * Permet d'ajouter de nouvelles compétences martiales à la liste déjà
 * établie.
 *
 * le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les messages de début et de fin de méthode.\n
 *
 * @param[in] aAjouter conteneur des compétences martiales.
 * 
 ******************************************************************************/
void Joueur::ajouterMartiales(const vector<unsigned>& aAjouter)
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::ajouterMartiales -> début" << endmsg;

  vector< unsigned > nouvelles;

  gererMartiales( aAjouter, nouvelles );

  J_Martiales.insert( J_Martiales.end(), nouvelles.begin(), nouvelles.end() );

  func() <<  "Joueur::ajouterMartiales -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/***************************************************************************//**
 *
 * Permet de déterminer les compétences diverses \e lors \e de \e la
 * \e création du PJ. Ici on détermine dans un premier temps les
 * scores ajustés, puis on écrit le résultat dans J_CompDiv.
 *
 * @param[in] vec conteneur des compétences diverses brutes (structure
 * Compétence - Valeur).
 *
 ******************************************************************************/
void Joueur::initDiverses(const vector<unsigned>& vec)
{
  vector<unsigned> tmp;

  gererDiverses( vec, tmp );

  setDiverses(tmp);
}

/**************************************************************************//**
 *
 * Fixe le nombre de pv du Joueur, à la création.
 *
 * @param[in] pv nombre de PV du PJ.
 *
 *****************************************************************************/
void Joueur::setPV(const unsigned& pv)
{
  PV = pv;
}

/**************************************************************************//**
 *
 * Sert à ajoutter une Classe, gestion du multiclassé lors de la
 * création, de la classe jumelée lors du jumelage.\n
 *
 * Si le PJ est humain, le type de PJ est changé en "PJ à classes
 * jumelées" au premier ajout. Pour les autre races, le type devient
 * "PJ à classes multiples".\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les message de début et de fin de méthode.
 *
 * @param[in] classe pointeur sur la classe à ajouter.
 *
 *****************************************************************************/
void Joueur::ajoutClasse(Classe* classe)
{
  /*Debug::*/empileNiveau( &interne );

  func() << "Joueur::ajoutClasse -> début" << endmsg;

  J_classe.push_back(classe);
  nb_classes++;
  if ( J_race -> type() == "Humain" )
    TM_switch = Jum;
  // Un Humain ne peut être que jumelé
  else
    TM_switch = Mul;
  // Un non-humain ne peut être que multiclassé

  J_CompAccess.insert( J_CompAccess.end(), classe -> tc() -> begin(),
		       classe -> tc() -> end());

  nettoieTC();

  unsigned TAc0_tmp(20);
  for (unsigned i(0); i < nb_classes; i++)
    {
      if (J_classe[i] -> calculeNombres() < TAc0_tmp)
	TAc0_tmp = J_classe[i] -> calculeNombres();
    }
  TAc0 = TAc0_tmp;

  func() << "Joueur::ajoutClasse -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Fonctions de sortie en .tex, écrit la feuille de personnage.\n
 *
 * Pour plus de modularité, on fait appel à des fonctions spécifiques
 * pour chaque fichier .tex à écrire..
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e INFO  affiche les fichiers .tex écrits.\n
 * \e FUNC  affiche les messages de début et de fin de méthode.\n
 * \e LFUNC  permet de vérifier la création du script.
 *
 * @param[in] UI sert à éviter le lancement du programme de visionnage
 * lors de l'utilisation du mode graphique. Sinon le programme se
 * metterait en pause en attendant que l'on ferme la fenêtre.
 *
 *****************************************************************************/
void Joueur::ecrireTex(const bool& UI) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::ecrireTex -> début" << endmsg;
  /* 
   * Initialisation : on édite un script shell qui va faire le boulot de
   * compilation une fois tous les fichiers créés
   */
  ifstream script_entree;
  script_entree.open("Joueur0/Finition.sh");
  ofstream script_sortie;
  script_sortie.open("tmp.sh");
  string ligne;
  size_t loc;

  while ( !script_entree.eof() )
    {
      getline(script_entree, ligne);
      loc = ligne.find("@", 0);
      if (loc != string::npos)
	ligne.replace(loc, 1, convertNom());
      if ( UI && ligne.find("&") != string::npos)
	continue;
      lfunc() << ligne << endmsg;
      script_sortie << ligne << endl;
    }
  
  script_entree.close();
  script_sortie.close();

  ecrireTraitsTex();
  info() << "Traits                   [ OK ]" << endmsg;
  ecrireJSTex();
  info() << "JS                       [ OK ]" << endmsg;
  ecrireScoresTex();
  info() << "Scores                   [ OK ]" << endmsg;
  ecrireRaceTex();
  info() << "Race                     [ OK ]" << endmsg;
  ecrireClasseTex();
  info() << "Classe                   [ OK ]" << endmsg;
  ecrireCompTex();
  info() << "Compétences              [ OK ]" << endmsg;
  ecrireSortsTex();
  info() << "Sorts                    [ OK ]" << endmsg;

  blank() << "Feuille de personnage écrite" << endmsg;

  func() << "Joueur::ecrireTex -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Donne le nombre de dons.
 *
 * @return la taille du conteneur J_Dons.
 * 
 *****************************************************************************/
unsigned Joueur::nbrDons() const
{
  return J_Dons.size();
}

/**************************************************************************//**
 *
 * Donne le nombre de désavantages.
 *
 * @return la taille du conteneur J_Desavantages.
 * 
 *****************************************************************************/
unsigned Joueur::nbrDesavantages() const
{
  return J_Desavantages.size();
}

/**************************************************************************//**
 *
 * Donne le nombre de compétences non martiales.
 *
 * @return la taille du conteneur J_CompDiv.
 * 
 *****************************************************************************/
unsigned Joueur::nbrCompetences() const
{
  return J_CompDiv.size();
}

/**************************************************************************//**
 *
 * Donne le nombre de compétences martiales.
 *
 * @return la taille du conteneur J_Martiales
 * 
 *****************************************************************************/
unsigned Joueur::nbrCompMartiales() const
{
  return J_Martiales.size();
}

/*******************************************************************************
 *
 * Les fonctions suivantes ont été ajoutées pour permettre d'écrire un
 * fichier xml avec Qt, c'est à dire à partir de la classe EcrireXML,
 * qui n'a pas accès aux membres de Joueur
 * 
 ******************************************************************************/

/***************************************************************************//**
 *
 * Donne le nom du Joueur, est utilisé lors de l'écriture d'un fichier
 * XML avec l'interface graphique, EcrireXML n'ayant pas accès aux
 * champs de Joueur.
 *
 * @return le nom du PJ
 *
 ******************************************************************************/
string Joueur::nom() const
{
  return Nom;
}

/***************************************************************************//**
 *
 * Donne la race du Joueur, est utilisé lors de l'écriture d'un
 * fichier XML avec l'interface graphique, EcrireXML n'ayant pas accès
 * aux champs de Joueur.
 *
 * @return la race du PJ (nom de la race).
 *
 ******************************************************************************/
string Joueur::race() const
{
  return J_race -> type();
}

/***************************************************************************//**
 *
 * Retourne un pointeur sur la Race du PJ est utilisé lors de
 * l'écriture d'un fichier XML avec l'interface graphique, EcrireXML
 * n'ayant pas accès aux champs de Joueur.
 *
 * @return J_race
 *
 ******************************************************************************/
const Race* Joueur::racePtr() const
{
  return J_race;
}

/***************************************************************************//**
 *
 * Permet d'accéder à la valeur d'un trait.
 *
 * @param[in] i numéro du trait voulu.
 *
 * @return une référence constante sur la valeur du trait voulu, ou
 * sur le score de Force (si l'indice n'est pas valide).
 *
 * @todo Définir une valeur bidon pour renvoyer en cas d'indice non
 * valide.
 *
 ******************************************************************************/
const unsigned& Joueur::trait( const unsigned& i ) const
{
  if ( i < 7 )
    return Traits[ i ];
  
  return Traits[ 0 ];
}

/***************************************************************************//**
 *
 * Permet de récupérer un pointeur sur les traits du personnage.
 *
 * @return l'adresse de Traits.
 *
 ******************************************************************************/
const vector< unsigned >* Joueur::traits() const
{
  return &Traits;
}

/***************************************************************************//**
 *
 * Donne le nombre de Classes du Joueur, est utilisé lors de
 * l'écriture d'un fichier XML avec l'interface graphique, EcrireXML
 * n'ayant pas accès aux champs de Joueur.
 *
 * @return la taille de J_classe
 *
 ******************************************************************************/
unsigned Joueur::nbrClasses() const
{
  return J_classe.size();
}

/***************************************************************************//**
 *
 * Retourne un pointeur sur la Classe du PJ, est utilisé lors de
 * l'écriture d'un fichier XML avec l'interface graphique, EcrireXML
 * n'ayant pas accès aux champs de Joueur.
 *
 * @param[in] i "numéro" de la classe désirée (index dans J_classe).
 *
 * @return J_classe[ i ]
 *
 ******************************************************************************/
Classe* Joueur::classePtr(const unsigned& i) const
{
  if ( i == 99)
    return J_classe.back();
  else
    return J_classe[i];
}

/***************************************************************************//**
 *
 * Donne accès aux traits du PJ, est utilisé lors de l'écriture d'un
 * fichier XML avec l'interface graphique, EcrireXML n'ayant pas accès
 * aux champs de Joueur.
 *
 * @param[out] tab tableau contenant les traits du PJ, sera modifié apr
 * la méthode
 *
 ******************************************************************************/
void Joueur::traits(unsigned tab[7]) const
{
  for (unsigned i(0); i < 7; i++)
    tab[i] = Traits[ i ];
}

/***************************************************************************//**
 *
 * Récupère la liste des capacités raciales du PJ, et retourne le tout
 * sous forme d'une chaîne de caractères où tout est déjà
 * concaténé. Est utilisé lors de l'écriture d'un fichier XML avec
 * l'interface graphique, EcrireXML n'ayant pas accès aux champs de
 * Joueur.
 *
 * @return string contenant la liste des capacités raciales, séparées
 * par des espaces.
 *
 ******************************************************************************/
string Joueur::capaRaciale() const
{
  unsigned nbr(J_race -> tailleCapacites()), tmp;

  string resultat("");

  for (unsigned i(0); i < nbr; i++)
    {
      tmp = J_race -> numCapacite( i );
      resultat += ecrireString( tmp ) + ' ';
    }

  return resultat;
}

/***************************************************************************//**
 *
 * Récupère le type de multi-classe du PJ.
 *
 * @return \e 1 si multiclassé,\e 2 si PJ à classes jumelées, \e 0 si
 * classe unique ou type corrompu.
 *
 ******************************************************************************/
unsigned Joueur::typeMulti() const
{
  switch(TM_switch)
    {
    case Non:
      return 0;
    case Mul:
      return 1;
    case Jum:
      return 2;
    default:
      warning() << "Type de multiclassage inconnu" << endmsg;
      return 0;
    }
}

/***************************************************************************//**
 *
 * Retourne le nombre de PV du PJ.
 *
 * @return nombre de points de vie.
 *
 ******************************************************************************/
unsigned Joueur::nbrPV() const
{
  unsigned pv(0);
  for (unsigned i(0); i < nb_classes; i++)
    pv += J_classe[i] -> pv();

  if ( TM_switch == Mul )
    pv /= nb_classes;
    
  return pv;
}

/***************************************************************************//**
 *
 * Retourne le nombre de PP du PJ.
 *
 * @return nombre de points de personnage.
 *
 ******************************************************************************/
unsigned Joueur::nbrPP() const
{
  return PP;
}

/***************************************************************************//**
 *
 * Récupère l'ajustement aux PV dû à la Consititution, sous forme
 * d'une string au format LaTeX.
 *
 * @return ajustement au format LaTeX
 *
 */
string Joueur::ajustementPV() const
{
  return Aj_Const[ Traits[ 2 ] - 1 ][ 0 ];
}

/***************************************************************************//**
 *
 * Permet de récupérer les accès aux compétences diverses. Le nombre
 * de catégories est également récupéré.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les messages de début et de fin de la méthode.\n
 * \e DEBUG affiche le nombre de catégories disponibles.
 *
 * @param[out] nbr est le nombre de catégories disponibles.
 *
 * @return un pointeur sur le conteneur des accès.
 *
 ******************************************************************************/
const vector<TypeClasse>* Joueur::acces(unsigned& nbr) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::acces -> début" << endmsg;
  
  nbr = J_CompAccess.size();

  debug() << "Nbr de types d'accès : " << nbr << endmsg;

  func() << "Joueur::acces -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);

  return &J_CompAccess;
}

/***************************************************************************//**
 *
 * Permet de récupérer les sorts d'une Classe donnée. Le nombre de
 * sorts est également récupéré.\n
 *
 * Par sorts, on entend bien sûr les sorts de Mage, Spécialistes et
 * Bardes. Les sorts de prêtres, que peuvent lancer les Clercs,
 * Druides, Rôdeurs et Paladins ne sont pas inclus dans cette
 * catégorie.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les messages de début et de fin de la méthode.\n
 * \e DEBUG affiche le nombre de sorts connus.
 *
 * @param[out] nbr est le nombre de sorts connus.
 * @param[in] i "numéro" de la classe (index de J_classe).
 *
 * @return un pointeur sur le conteneur des sorts.
 *
 ******************************************************************************/
const vector<Sort>* Joueur::sorts(unsigned& nbr, const unsigned& i)
  const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::sorts -> début" << endmsg;

  nbr = J_classe[i] -> nbrSortsConnus();

  debug() << "Nbr de sorts : " << nbr << endmsg;

  func() << "Joueur::sorts -> fin" << endmsg;
  /*Debug::*/depileNiveau();

  return J_classe[i] -> adresseSorts();
}

/***************************************************************************//**
 *
 * Permet de récupérer les accès aux dons. Le nombre de dons est
 * également récupéré.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les messages de début et de fin de la méthode.\n
 * \e DEBUG affiche le nombre de dons.
 *
 * @param[out] nbr est le nombre de dons.
 *
 * @return un pointeur sur le conteneur des dons.
 *
 ******************************************************************************/
const vector<unsigned>* Joueur::dons(unsigned& nbr) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::dons -> début" << endmsg;

  nbr = J_Dons.size();

  debug() << "Nbr de dons : " << nbr << endmsg;

  func() << "Joueur::dons -> fin" << endmsg;
  /*Debug::*/depileNiveau();

  return &J_Dons;
}

/***************************************************************************//**
 *
 * Permet de récupérer les accès aux désavantages. Le nombre de
 * désavantages est également récupéré.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les messages de début et de fin de la méthode.\n
 * \e DEBUG affiche le nombre de desavantages.
 *
 * @param[out] nbr est le nombre de desavantages.
 *
 * @return un pointeur sur le conteneur des desavantages.
 *
 ******************************************************************************/
const vector<unsigned>* Joueur::desavantages(unsigned& nbr) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::desavantages -> début" << endmsg;

  nbr = J_Desavantages.size();

  debug() << "Nbr de désavantages : " << nbr << endmsg;

  func() << "Joueur::desavantages -> fin" << endmsg;
  /*Debug::*/depileNiveau();

  return &J_Desavantages;
}

/***************************************************************************//**
 *
 * Permet de récupérer les compétences diverses, Leur nombre est
 * également récupéré.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les messages de début et de fin de la méthode.\n
 * \e DEBUG affiche le nombre de compétences diverses.
 *
 * @param[out] nbr est le nombre de compétences diverses.
 *
 * @return un pointeur sur le conteneur des compétences diverses.
 *
 ******************************************************************************/
const vector<unsigned>* Joueur::diverses(unsigned& nbr) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::diverses -> début" << endmsg;

  nbr = J_CompDiv.size();

  debug() << "Nbr de compétences diverses : " << nbr << endmsg;

  func() << "Joueur::diverses -> fin" << endmsg;
  /*Debug::*/depileNiveau();

  return &J_CompDiv;
}

/***************************************************************************//**
 *
 * Permet de récupérer les compétences martiales, Leur nombre est
 * également récupéré.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC affiche les messages de début et de fin de la méthode.\n
 * \e DEBUG affiche le nombre de compétences martiales.
 *
 * @param[out] nbr est le nombre de compétences martiales.
 *
 * @return un pointeur sur le conteneur des compétences martiales.
 *
 ******************************************************************************/
const vector<unsigned>* Joueur::martiales(unsigned& nbr) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::martiales -> début" << endmsg;

  nbr = J_Martiales.size();

  debug() << "Nbr de compétences martiales : " << nbr << endmsg;

  func() << "Joueur::martiales -> fin" << endmsg;
  /*Debug::*/depileNiveau();

  return &J_Martiales;
}

/***************************************************************************//**
 *
 * Permet de récupérer la liste de tous les dons existants, leur
 * nombre est également récupéré. Est utilisé lors du choix des dons
 * par interface graphique.
 *
 * @param[out] vec conteneur des dons, est modifié par la méthode
 *
 * @return nombre de dons existants
 *
 ******************************************************************************/
unsigned Joueur::listeDons(vector<CapaciteRaciale> &vec) const
{

  unsigned taille( Dons.size() );

  vec.assign( Dons.begin(), Dons.end() );

  return taille;
}

/***************************************************************************//**
 *
 * Permet de récupérer la liste de tous les désavantages existants,
 * leur nombre est également récupéré. Est utilisé lors du choix des
 * désavantages par interface graphique.
 *
 * @param[out] vec conteneur des désavantages, est modifié par la
 * méthode.
 *
 * @return nombre de désavantages existants
 *
 ******************************************************************************/
unsigned Joueur::listeDesavantages(vector<CapaciteRaciale> &vec) const
{
  vec.clear();

  unsigned taille( Desavantages.size() );

  vec.assign( Desavantages.begin(), Desavantages.end() );

  return taille;
}

/***************************************************************************//**
 *
 * Permet de récupérer la liste des catégories de compétences diverses
 * existantes, leur nombre est également récupéré. Est utilisé lors du
 * choix des compétences diverses par interface graphique.
 *
 * @param[out] nbr nombre de catégories existants, écrit par la
 * méthode.
 *
 * @return pointeur sur le premier élément de la liste.
 *
 ******************************************************************************/
const string* Joueur::listeCategories(unsigned& nbr) const
{
  nbr = sizeof(CategoriesCompetences) / sizeof(*CategoriesCompetences);

  return &CategoriesCompetences[0];
}

/***************************************************************************//**
 *
 * Permet de récupérer la liste des compétences diverses existantes,
 * leur nombre est également récupéré. Est utilisé lors du choix des
 * compétences diverses par interface graphique.
 *
 * @param[out] nbr nombre de compétences diverses existants, écrit par
 * la méthode.
 *
 * @return pointeur sur le premier élément de la liste.
 *
 ******************************************************************************/
const vector< NonMartiale >* Joueur::listeCompetences(unsigned& nbr) const
{
  nbr = CompetencesDiverses.size();

  return &CompetencesDiverses;
}

/***************************************************************************//**
 *
 * Permet de récupérer une compétence particulière dans la liste
 * Joueur::CompétencesDiverses. On vérifie premièrement que cette
 * compétence existe !
 *
 * @param[in] i "numéro" de la compétence (index dans
 * CompétencesDiverses).
 *
 * @return la compétence voulue, ou une compétence "Inconnue" en cas
 * d'erreur.
 *
 ******************************************************************************/
const NonMartiale& Joueur::compDsListe(const unsigned& i) const
{
  if ( i >= CompetencesDiverses.size() )
    {
      warning() << "Compétence inconnue!" << endmsg;
      return nonMartialeInconnue();
    }

  return CompetencesDiverses . at( i );
}

/***************************************************************************//**
 *
 * Permet de récupérer la liste des armes diponibles à la Classe donnée.
 *
 * @param[in] nomClasse nom de la classe.
 *
 * @return un pointeur sur le conteneur des armes disponibles.
 *
 ******************************************************************************/
const vector<unsigned>* Joueur::martialeClasse(const string& nomClasse)
  const
{
  return CompMartialesParClasse[GererClasses.find( nomClasse ) -> second];
}

/***************************************************************************//**
 *
 * Permet de récupérer le niveau de magie du PJ. On itère sur les
 * classes disponibles et on prend le maximum.
 *
 * Cela peut paraître dangereux, mais cette méthode est utilisée
 * uniquement pour contrôler que l'on peut ajouter des sorts à ce PJ.
 *
 * @return niveau de magie (maximal si plusieurs classes) du PJ.
 *
 ******************************************************************************/
const unsigned& Joueur::niveauMagie() const
{
  vector< Classe* >::const_iterator it, End( J_classe.end() ), minIt;
  unsigned niv( 0 );

  for ( it = J_classe.begin(); it != End; it++ )
    {
      if ( (*it) -> niveauMagie() >= niv )
	{
	  niv = (*it) -> niveauMagie();
	  minIt = it;
	}
    }

  return (*minIt) -> niveauMagie();
}

/**************************************************************************//**
 *
 * Permet de fixer les niveaux de sorties des différentes
 * fonctions. Est utilisé dans la fonction lireNiveauxSortie().
 *
 * @param[in] level niveau de sortie à stocker.
 * @param[in] n "numéro" du niveau de sortie.
 * 
 *****************************************************************************/
void Joueur::setLevel(const unsigned& level, const unsigned& n)
{
  switch(n)
    {
    case 1:
      interne = static_cast< DebugLevelType >( level );
      break;
    case 2:
      fonction_elementaire_xml = static_cast< DebugLevelType >( level );
      break;
    case 3:
      fonction_recuperation_xml = static_cast< DebugLevelType >( level );
      break;
    case 4:
      fonction_tex = static_cast< DebugLevelType >( level );
      break;
    default:
      FlotMessage warn( WARN, "Joueur" );
      warn<< "Variable inconnue, dans Joueur::setLevel" << endmsg;
    }
}

/***************************************************************************//**
 *
 * Regarde si le Joueur possède des sorts de mage (=> mage,
 * spécialiste, barde avec compétence) et remplit vec avec les
 * pointeurs sur les classe possédant de tels sorts.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC permet d'afficher un message au début et à la fin de la
 * méthode.\n
 * \e DEBUG permet d'afficher toutes les classes.\n
 *
 * @param[out] vec contiendra les pointeurs vers les classes possédant
 * des sorts
 *
 * @return le nom du personnage (pour pouvoir créer le fichier au bon
 * endroit)
 */
string Joueur::aSortsMage(vector<Classe *>& vec) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::aSortsMage -> début" << endmsg;

  unsigned i, nbr_capa;
  string quoi, retour("");

  vec.clear();

  for(i = 0; i < nb_classes; i++)
    {
      quoi = J_classe[i] -> classe();
      debug() << quoi << endmsg;
      if (quoi == "Mage" || quoi == "Spécialiste")
	vec.push_back(J_classe[i]);
      else if (quoi == "Barde")
	{
	  nbr_capa = J_classe[i] -> tailleCompetences();
	  for (unsigned j(0); j < nbr_capa; j++)
	    {
	      if (J_classe[i] -> numCompetence(j) == 12)
		{
		  vec.push_back(J_classe[i]);
		  break;
		}
	    }
	}
    }

  if (!vec.empty())
    retour = Nom;

  func() << "Joueur::aSortsMage -> fin" << endmsg;
  /*Debug::*/depileNiveau();

  return retour;
}

/**************************************************************************//**
 *
 * Racourci pour savoir si le personnage peut se spécialiser dans une
 * compétence martiale. On parcourt les classes dérivées et on renvoie le
 * résultat le plus avantageux.
 *
 * @return 0 si aucune spécialisation n'est possible, 1 si une spécialisation
 * est possible et finalement 2 pour les spécialisations multiples (accessibles
 * au guerriers uniquement).
 * 
 *****************************************************************************/
unsigned Joueur::aSpecialisation() const
{
  vector< unsigned > parClasse( nbrClasses() );

  transform( J_classe.begin(), J_classe.end(), parClasse.begin(),
	     bind< unsigned >( &Classe::aSpecialisation, _1 ) );

  return *max( parClasse.begin(), parClasse.end() );
}


/**************************************************************************//**
 *
 * Sert à ajouter dons ou désavantages. Cette méthode n'ets employée
 * uniquement lors de la création, puisqu'il est impossible d'acquérir
 * un don ou désavantage en cours de jeu.
 * 
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC  affiche les messages de début et de fin de méthode.\n
 * \e DEBUG permet d'afficher le contrôle Dons / Désavatages 
 *
 * @param[in] quoi peut être soit Don soit Désavantage (enum).
 *
 *****************************************************************************/
void Joueur::determinerDonsDesavantages(const TypeComp& quoi)
{
  /*Debug::*/empileNiveau( &interne );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(interne);
  func() << "Joueur::determinerDonsDesavantages -> début" << endmsg;
  const CapaciteRaciale *liste;
  vector<unsigned>* vec;
  unsigned taille, i, save_PP(PP), vec_taille;
  bool ok(true), desav;
  switch(quoi)
    {
    case Don:
      debug() << "Joueur::determinerDonsDesavantages => don" << endmsg;
      liste = &Dons[0];
      vec = &J_Dons;
      taille = 27;
      desav = false;
      break;
    case Desav:
      debug() << "Joueur::determinerDonsDesavantages => désavantage"
	      << endmsg;
      liste = &Desavantages[0];
      vec = &J_Desavantages;
      taille = 38;
      desav = true;
      break;
    default:
      warning() << "Joueur::determinerDonsDesavantages => inconnu" << endmsg;
      ok = false;
      taille = 0;
      break;
    }
  debug() << "nbr " << taille << endmsg;
  
  unsigned nbr;
  bool test(true), encore(false);
  
  if (ok)
    {
      blank() << setfill('*') << setw(56) << '*' << endmsg;
      for (i = 0; i < taille; i++, liste++)
	blank() << i+1 << ' ' << liste -> nom()
		<< " (" << liste -> prix() << " pp)" << endmsg;
      blank() << i+1 << " Aucune" << endmsg;
      
      liste -= taille;
      
      do
	{
	  while(test)
	    {
	      blank() << '(' << PP << " pp restants) " << endaff;
	      cin >> nbr;
	      if (nbr!=taille+1)
		{
		  
		  if (PP >= (liste + nbr - 1) -> prix() || desav)
		    {
		      switch(quoi)
			{
			case Don:
			  PP -= (liste + nbr - 1) -> prix();
			  break;
			case Desav:
			  PP += (liste + nbr - 1) -> prix();
			  break;
			}
		      vec -> push_back(nbr-1);
		      blank() << "Choisi : "
			      << (liste + nbr - 1) -> nom() << endmsg;
		    }
		  else
		    blank() << "Pas assez de pp" << endmsg;
		  
		}
	      else
		test = false;
	    }
	  vec_taille = vec -> size();
	  for (i = 0; i < vec_taille; i++)
	    blank() << i + 1 << " " << (liste + (*vec)[i]) -> nom() << endmsg;
	  blank() << endmsg <<  "1 pour continuer, 2 pour recommencer" << endmsg;
	  nbr = demanderUnsignedBorne("Choix ", 1, 2);
	  if (nbr == 2)
	    {
	      PP = save_PP;
	      vec -> clear();
	      test = true;
	      encore = true;
	      blank() << endmsg;
	    }
	  else
	    encore = false;
	}
      while(encore);
      blank() << endmsg << setfill('*') << setw(56) << '*' << endmsg;
    }

  func() << "Joueur::determinerDonsDesavantages -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Sert à rajoutter des compétences diverses. Est utilisé lors de la
 * création du PJ et en cours de partie, lorsque le PJ apprend de
 * nouvelles compétences.\n
 *
 * A chaque fois qu'un compétence est sélectionnée, on vérifie qu'elle
 * n'est pas déjà prise.\n
 *
 * Dans cette méthode on rempli un conteneur avec uniquement les
 * numéros des compétences choisies. On passe ensuite ce conteneur à
 * la méthode gererDiverses, qui va s'occuper du score de chaque
 * compétence choisie.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC  affiche les messages de début et de fin de méthode.\n
 * \e DEBUG affiche des information de contrôle, comme le nombre de
 * compétences, le prix de la compétence choisie.
 *
 *****************************************************************************/
void Joueur::determinerCompetences()
{
  /*Debug::*/empileNiveau( &interne );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(interne);
  func() << "Joueur::determinerCompetences -> début" << endmsg;
  unsigned taille(83), i, nbr, tot(J_CompAccess.size());
  bool test(true), encore(false);
  unsigned save_PP(PP), vec_taille, supplement, quelle,
    inf(100), sup(0);
  vector<unsigned> temp_vec, choix, deja;

  vector<TypeClasse>::const_iterator Begin(J_CompAccess.begin()),
    End(J_CompAccess.end()), it;
  
  for ( i = 0; i < tot; i += 2 )
    deja.push_back( J_CompDiv[ i ] );

  vector< unsigned >::const_iterator dejaBegin( deja.begin() ),
    dejaEnd( deja.end() );

  debug() << "nbr catégories comp non-martiales : " << tot / 2 << endmsg;
  
  do
    {
      do
	{
	  blank() << endmsg <<"Catégories de compétences non martiales :"
		  << endmsg;
	  for (i = 0; i < 5; i++)
	    {
	      blank() << i + 1 << " " << CategoriesCompetences[i];
	      if ( find( Begin, End, static_cast< TypeClasse >( i ) ) != End )
		blank() << endmsg;
	      else
		blank() << "  - cout supplémentaire 5pp" << endmsg;
	    }
	  blank() << "6 Sortir" << endmsg;
	  
	  quelle = demanderUnsignedBorne("Quelle catégorie de compétence ? ",
					   1, 6);
	  blank() << endmsg;
	  inf = 100;
	  sup = 0;
	  
	  if (quelle == 6)
	    break;
	  
	  if ( find( Begin, End, static_cast< TypeClasse>( quelle - 1 ) ) != End )
	    supplement = 0;
	  else
	    supplement = 5;
	  
	  for (i = 0; i < taille; i++)
	    {
	      if ( CompetencesDiverses[i].categorieAdmise() !=
		   TypeClasse( quelle - 1) )
		continue;
	      if (i + 1 < inf) inf = i + 1;
	      if (i + 1 > sup) sup = i + 1;
	      blank() << i+1 << ' ' << CompetencesDiverses[i].nom()
		      << " (" << CompetencesDiverses[i].prix() + supplement
		      << " pp)" << endmsg;
	    }
	  blank() << sup + 1 << " Retour" << endmsg;
	  
	  do
	    {
	      nbr = demanderUnsignedBorne("("+ecrireString(PP)+" pp restants) ", inf,
					    sup + 1);
	      
	      if (nbr != sup + 1)
		{
		  if ( find( dejaBegin, dejaEnd, nbr - 1 ) != dejaEnd )
		    warning() << "Compétence martiale déjà prise !" << endmsg;
		  if (PP >= CompetencesDiverses[nbr-1].prix() + supplement)
		    {
		      PP -= (CompetencesDiverses[nbr-1].prix() + supplement);
		      choix.push_back(nbr-1);
		      // Attention, on tente de changer le procesus!
		      //  temp_vec.push_back(CompetencesDiverses[nbr-1].Valeur);
		      //  t_1 = CompetencesDiverses[nbr-1].Trait1;
		      //  t_2 = CompetencesDiverses[nbr-1].Trait2;
		      //  if (t_1 != 255 && t_2 != 255)
		      //  {
		      //  if (J_classe[0] -> get_trait(t_1) < J_classe[0] -> get_trait(t_2))
		      //  tmp = J_classe[0] -> get_trait(t_2);
		      //  else
		      //  tmp = J_classe[0] -> get_trait(t_1);
		      //  }
		      //  else if (t_1 != 255)
		      //  tmp = J_classe[0] -> get_trait(t_1);
		      //  modificateur_val(temp_vec.back(), tmp);
		      blank() << "Compétence non-martiale choisie : "
			      << CompetencesDiverses.at( nbr - 1 ).nom()
			      << endmsg;
		    }
		  else
		    blank() << "Pas assez de pp" << endmsg;
		}
	    }
	  while (nbr != sup + 1);
	}
      while (true);

      gererDiverses(choix, temp_vec);

      vec_taille = temp_vec.size();
      for (i = 0; i < vec_taille; i+=2)
	blank() << (i / 2) + 1 << " "
		<< CompetencesDiverses.at( temp_vec[i] ).nom() << " "
		<< temp_vec[i + 1] <<  endmsg;
      blank() << endmsg <<  "1 pour continuer, 2 pour recommencer"
	      << endmsg;
      nbr = demanderUnsignedBorne("Choix ", 1, 2);
      if (nbr == 2)
	{
	  PP = save_PP;
	  temp_vec.clear();
	  test = true;
	  encore = true;
	  blank() << endmsg;
	}
      else
	encore = false;
    }
  while (encore);

  J_CompDiv.insert(J_CompDiv.end(), temp_vec.begin(), temp_vec.end());

  blank() << endmsg << setfill('*') << setw(56) << '*' << endmsg;

  func() << "Joueur::determinerCompetences -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Sert à augmenter les compétences non-martiales, c'est à dire permet
 * l'augmentation des talent. Pour chaque compétence diverse connue,
 * on regarde le score associé et on propose à l'utilisateur
 * d'augmenter ces compétences.\n
 *
 * Une fois le processus d'augmentation des talents effectué, un
 * récapitulatif de l'évolution des compétences est affiché et
 * l'utilisateur peut annuler son choix.\n
 *
 * Une fois le choix confirmé, les changements sont sauvés et le
 * nombre de PP du PJ est mis à jour.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e INFO  affiche si le PF peut sélectionner un groupe entier.\n
 * \e FUNC  affiche les messages de début et de fin de méthode.\n
 *
 *****************************************************************************/
void Joueur::augmenterCompetences()
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::augmenterCompetences -> début" << endmsg;

  unsigned taille(nbrCompetences()), i, nbr, derniere, combien,
    save_PP(PP);
  bool test(true), encore(false);
  vector<unsigned> temp_vec; // copie temporaire
  temp_vec.assign(J_CompDiv.begin(), J_CompDiv.end());

  for(i = 0; i < taille; i+=2)
    blank() << i / 2 + 1 << " " << CompetencesDiverses.at(J_CompDiv[i]).nom()
	    << " " << J_CompDiv[i+1] << endmsg;

  derniere = (taille + 1) / 2 + 1;
  blank() << derniere << " Terminé" << endmsg;

  do
    {
      do
	{
	  nbr = demanderUnsignedBorne("Quelle compétence améliorer ? (" +
					ecrireString(PP) + " PP restants) ",
					1, derniere);
	  if (nbr == derniere)
	    test = false;
	  else if (PP == 0)
	    test = false;
	  else
	    {
	      combien = demanderUnsignedBorne("De combien ? ", 1, PP);
	      temp_vec[(nbr - 1) * 2 + 1] += combien;
	      PP -= combien;
	    }
	  if (PP == 0)
	    test = false;
	}
      while(test);
    
      for(i = 0; i < taille; i+=2)
	blank() << i / 2 + 1 << " "
		<< CompetencesDiverses.at(J_CompDiv[i] ).nom() << " "
		<< J_CompDiv[i+1] << " -> " << temp_vec[i+1] << endmsg;
      
      blank() << endmsg <<  "1 pour continuer, 2 pour recommencer" << endmsg;
      nbr = demanderUnsignedBorne("Choix ", 1, 2);
      if (nbr == 2)
	{
	  PP = save_PP;
	  test = true;
	  encore = true;
	  temp_vec.clear();
	  temp_vec.assign(J_CompDiv.begin(), J_CompDiv.end());
	  blank() << endmsg;
	}
      else
	encore = false;
    }
  while(encore);

  J_CompDiv.clear();
  J_CompDiv.assign(temp_vec.begin(), temp_vec.end());
  
  func() << "Joueur::augmenterCompetences -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Sert à déterminer les compétences martiales du PJ. La sélection se
 * fait en plusieurs étapes : on sélectionne en premier le groupe
 * large, puis le groupe restreint et seulement ensuite la liste des
 * armes disponibles s'affiche. S'il n'existe pas de groupe large pour
 * une catégorie d'armes, le groupe restreint est traité comme un
 * groupe large.\n
 *
 * Un combattant a la possibilité d'apprendre un groupe (large ou
 * restreint) en entier. Pour le moment il n'est pas tenu compte des
 * compétences éventuelles déjà acquises dans le calcul du coût.\n
 *
 * La liste des armes est lue depuis le fichier ListeArmes.h.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC  affiche les messages de début de de fin de méthode.\n
 * \e LFUNC affiche les catégories d'armes disponibles ainsi que la
 * recherche des catégorie lors de la sélection.\n
 * \e DEBUG affiche le prix calculé de chaque compétence martiale
 * sélectionnée.
 *
 *****************************************************************************/
void Joueur::determinerCompMartiales()
{
  /*Debug::*/empileNiveau( &interne );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(interne);
  func() << "Joueur::determinerCompMartiales -> début" << endmsg;

  unsigned i, taille(J_classe.size());

  bool tout_dispo(false);

  map<string, unsigned> acces, *ptrAcces;
  ptrAcces = &acces;

  string tmpClasse;

  for (i = 0; i < taille; i++)
    {
      tmpClasse = J_classe[i] -> classe();
      if (tmpClasse == "Guerrier" || tmpClasse ==  "Rôdeur" ||
	  tmpClasse == "Paladin")
	tout_dispo = true;
      J_classe[i] -> prixAcces(ptrAcces);
    }

  if (tout_dispo)
    info() << "Possibilité d'apprendre des groupes de compétences" << endmsg;

  map<string, unsigned>::const_iterator mapIt, mapBegin(acces.begin()),
    mapEnd(acces.end());

  for (mapIt = mapBegin; mapIt != mapEnd; mapIt++)
    lfunc() << setfill(' ') << setw(11) << left << mapIt -> first
	    << " -> " << mapIt -> second << " pp" << endmsg;

  unsigned quelle, nbr, inf, sup, prix(100), vec_taille, save_PP(PP), quoi;
  bool encore(true), test(false);
  vector<unsigned> temp_vec, oublier;
  const vector<unsigned>* ptr;

  const vector< Martiale > * ListeArmes = LireArmesXML -> listeArmes();

  for ( i = 0; i < taille; i++ )
    {
      if ( i % 2 == 1 )
	oublier.push_back( i );
    }

  const vector< GLarge > * GroupesLarges = LireArmesXML -> groupesLarges();

  do
    {
      do
	{
	  blank() << endmsg <<"Catégories de compétences martiales :"
		  << endmsg;
	  for (i = 0; i < 12; i++)
	    {
	      blank() << i + 1 << " " << GroupesLarges -> at(i) .Nom
		      <<  endmsg;
	    }
	  blank() << "14 Sortir" << endmsg;
	  
	  quelle = demanderUnsignedBorne("Quelle catégorie de compétence ? ",
					   1, 14);
	  blank() << endmsg;
	  inf = 210;
	  sup = 0;
	  
	  if (quelle == 14)
	    break;
	  
	  taille = GroupesLarges -> at( quelle - 1 ) . Restreints;

	  if (taille == 0)
	    {
	      /*
	       * Ici on traite les groupes restreints qui n'appartiennent
	       * pas à un groupe large, càd les arbalètes, arcs, etc
	       */
	      for (i = 0; i < 205; i++)
		{
		  if (ListeArmes -> at( i ).groupeLarge() != (quelle - 1))
		    continue;
		  if (i + 1 < inf) inf = i + 1;
		  if (i + 1 > sup) sup = i + 1;
		  if (ListeArmes -> at( i ).nom().substr(0, 1) == "-")
		    continue;
		  blank() << i+1 << ' ' << ListeArmes -> at( i ).nom() << endmsg;
		}
	      blank() << sup + 1 << " Retour" << endmsg;
	  
	    }
	  else
	    {
	      /*
	       * Maintenant on s'occupe des groupes larges. Dans un premier
	       * temps on choisi un groupe restreint, qui sera ensuite
	       * affiché comme dans le cas précédent.
	       */
	      for (i = 0; i < taille; i++)
		blank() << i + 1 << ' '
			<< GroupesLarges -> at( quelle-1 ) . NomsRestreints[i]
			<< endmsg;
	      blank() << taille + 1 << " Sortir" << endmsg;
	  
	      quoi = demanderUnsignedBorne("Quelle catégorie de compétence ? ",
					     1, taille + 1);
	      blank() << endmsg;

	      if (quoi == taille + 1)
		break;

	      if (quoi == taille)
		quoi = 0;

	      for (i = 0; i < 205; i++)
		{
		  if (ListeArmes -> at( i ).groupeLarge() != (quelle - 1))
		    continue;
		  if  (ListeArmes -> at( i ).groupeRestreint() != (quoi))
		    continue;
		  if (i + 1 < inf) inf = i + 1;
		  if (i + 1 > sup) sup = i + 1;
		  if (ListeArmes -> at( i ).nom().substr(0, 1) == "-")
		    continue;
		  blank() << i + 1 << ' ' << ListeArmes -> at( i ).nom() << endmsg;
		}
	      blank() << sup + 1 << " Retour" << endmsg;
	    }

	  // Mais à partir de là c'est de nouveau commun, ouf!
	  do
	    {
	      nbr = demanderUnsignedBorne("("+ecrireString(PP)+" pp restants) ",
					    inf, sup + 1);
	      
	      if (nbr != sup + 1)
		{
		  prix = 20;
		  for (mapIt = mapBegin; mapIt != mapEnd; mapIt++)
		    {
		      tmpClasse = mapIt -> first;
		      lfunc() << "On cherche " << tmpClasse << endmsg;
		      ptr = CompMartialesParClasse[GererClasses.find(tmpClasse) -> second];
		      
		      if (ptr == 0)
			// Combattants => on l'a de toute façon
			{
			  debug() << "Prix = " << mapIt -> second << endmsg;
			  if (mapIt -> second < prix)
			    prix = mapIt -> second;
			}
		      else if (find(ptr -> begin(), ptr -> end(), nbr - 1) != ptr -> end())
			{
			  debug() << "Prix = " << mapIt -> second << endmsg;
			  if (mapIt -> second < prix)
			    prix = mapIt -> second;;
			}
		    }
		  if (prix != 20)
		    {
		      linfo() << "Prix final : " << prix << endmsg;
		      // Chercher coût ici
		      if (PP >= prix)
			{
			  if ( ! ( safePushBack(&J_Martiales, nbr - 1, oublier )
				   && safePushBack( &temp_vec, nbr - 1 ) ) )
			    {
			      temp_vec.push_back(nbr - 1);
			      PP -= prix;
			    }
			  else
			    warning() << "Compétence déjà prise" << endmsg;
			}
		      else
			blank() << "Pas assez de pp" << endmsg;
		    }
		  else
		    blank() << "Compétence inaccessible" << endmsg;
		}
	    }
	  while (nbr != sup + 1);
	}
      while (true);
      vec_taille = temp_vec.size();
      for (i = 0; i < vec_taille; i++)
	blank() << i + 1 << " "
		<< ListeArmes -> at( temp_vec[i] ).nom() <<  endmsg;
      blank() << endmsg <<  "1 pour continuer, 2 pour recommencer"
	      << endmsg;
      nbr = demanderUnsignedBorne("Choix ", 1, 2);
      if (nbr == 2)
	{
	  PP = save_PP;
	  temp_vec.clear();
	  test = true;
	  encore = true;
	  blank() << endmsg;
	}
      else
	encore = false;
    }
  while (encore);

  vector< unsigned > vec;

  gererMartiales( temp_vec, vec );

  J_Martiales.insert(J_Martiales.end(), vec.begin(), vec.end());

  func() << "Joueur::determinerCompMartiales -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Permet la progression des compétences martiales, càd aquérir une
 * spécialisation, maîtrise, ... Les personnages ne pouvant pas avoir
 * accès à une spécialisation peuvent toutefois choisir leur \e arme
 * \e de \e prédilection et prendre une \e expertise \e martiale.
 *
 *****************************************************************************/
void Joueur::augmenterCompMartiales()
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::augmenterCompMartiales -> début" << endmsg;

  if ( J_Martiales.size() % 2 != 0 )
    {
      warning() << "La taille du conteneur est impaire" << endmsg;
      func() << "Joueur::augmenterCompMartiales -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      return;
    }

  const vector< Martiale > * ListeArmes = LireArmesXML -> listeArmes();

  vector< unsigned >::iterator it, Begin( J_Martiales.begin() ),
    End( J_Martiales.end() );

  map< unsigned, unsigned > CompetenceEtNiveau;
  map< unsigned, unsigned >::iterator mapIt, mapBegin, mapEnd;

  for ( it = Begin; it != End; it++ )
    CompetenceEtNiveau.insert( make_pair( *it, *(++it) ) );

  mapBegin = CompetenceEtNiveau.begin();
  mapEnd   = CompetenceEtNiveau.end();

  unsigned choixPreExistant( -1u );

  vector< unsigned > indexes( CompetenceEtNiveau.size() );

  ExtraireClef< unsigned, unsigned > lectureCle;

  transform( mapBegin, mapEnd, indexes.begin(), lectureCle );

  // Arme de prédilection
  blank() << "Choix d'une arme de prédilection" << endmsg;

  unsigned indice( 1 );
  
  for ( mapIt = mapBegin; mapIt != mapEnd; mapIt++, indice++ )
    {
      blank() << indice << ' ' << ListeArmes -> at( mapIt -> first );
      if ( ( mapIt -> second & 8 >> 3 ) == 1 )
	{
	  choixPreExistant = indice - 1;
	  blank() << " (choix actuel)";
	}
      blank() << endmsg;
    }
  blank() << ++indice
	  << " Aucune (ou conserver le choix actuel)" << endmsg;

  unsigned choix, confirmation( 1 ), coutPred( prixArmePredilection() );

  do
    {
      choix = demanderUnsignedBorne( "Entrer le choix d'arme de prédilection",
				     1, indice );

      if ( choix != indice )
	{
	  if ( ( choixPreExistant != -1u && PP > 2 * coutPred ) ||
	       PP > coutPred )
	    blank() << "Choix : " << ListeArmes -> at( indexes[ choix - 1 ] )
		    << endmsg;
	  else
	    {
	      warning() << "Pas assez de PP" << endmsg;
	      choix = indice;
	    }
	}
      else
	blank() << "Aucun changement souhaité" << endmsg;

      confirmation = demanderUnsignedBorne( "1 = Annuler, 2 = Continuer",
					    1, 2 );
    }
  while( confirmation == 1 );

  if ( choix != indice )
    {
      if ( choixPreExistant != -1u )
	{
	  /*
	   * Il faut d'abord supprimer la précédente arme de
	   * prédilection (ce qui coûte).
	   */
	  CompetenceEtNiveau[ choixPreExistant ] -= 8;
	  PP -= coutPred;
	  blank() << "Suppression de l'arme de prédilection "
		  << ListeArmes -> at( choixPreExistant )
		  << endmsg;
	}
      CompetenceEtNiveau[ indexes[ choix - 1 ] ] += 8;
      PP -= coutPred;
      blank() << "Ajout de l'arme de prédilection "
	      << ListeArmes -> at( indexes[ choix - 1 ] )
	      << endmsg;

      for ( mapIt = mapBegin; mapIt != mapEnd; mapIt++, indice++ )
	{
	  it = find( Begin, End, mapIt -> first );
	  if ( *(it + 1) != mapIt -> second )
	    {
	      linfo() << ListeArmes -> at( *it ) << " : "
		      << *(it + 1) << " -> " << mapIt -> second
		      << endmsg;
	      *(it + 1) = mapIt -> second;
	    }
	}
    }

  // Expertise martiale
  unsigned coutExpert( prixExpertiseMartiale() ), pred( -1u );

  for ( mapIt = mapBegin, indice = 1, choixPreExistant = -1u;
	mapIt != mapEnd; mapIt++, indice++ )
    {
      blank() << indice << ' ' << ListeArmes -> at( mapIt -> first );
      if ( ( mapIt -> second & 16 >> 3 ) == 1 )
	{
	  choixPreExistant = indice - 1;
	  blank() << " (choix actuel)";
	}
      if ( ( mapIt -> second & 8 ) >> 3 == 1 )
	{
	  pred = indice - 1;
	  blank() << " (arme de prédilection)";
	}
      blank() << endmsg;
    }
  blank() << ++indice
	  << " Aucune (ou conserver le choix actuel)" << endmsg;

  do
    {
      choix = demanderUnsignedBorne( "Entrer le choix pour expertise martiale",
				     1, indice );
      
      if ( choix != indice )
	{
	  if ( choix - 1 != pred && ( ( ( choixPreExistant != -1u && PP > 2 * coutExpert ) ||
					PP > coutExpert ) ) )
	    blank() << "Choix : " << ListeArmes -> at( indexes[ choix - 1 ] )
		    << endmsg;
	  else if ( ( choixPreExistant != -1u && PP > 2 * ( coutExpert - 1 ) ) ||
		    PP > coutExpert - 1 )
	    blank() << "Choix : " << ListeArmes -> at( indexes[ choix - 1 ] )
		    << endmsg;
	  else
	    {
	      warning() << "Pas assez de PP" << endmsg;
	      choix = indice;
	    }
	}
      else
	blank() << "Aucun changement souhaité" << endmsg;
      
      confirmation = demanderUnsignedBorne( "1 = Annuler, 2 = Continuer",
					    1, 2 );
    }
  while( confirmation == 1 );
  
  if ( choix != indice )
    {
      if ( choixPreExistant != -1u )
	{
	  /*
	   * Il faut d'abord supprimer la précédente expertise martiale (ce qui coûte).
	   */
	  CompetenceEtNiveau[ choixPreExistant ] -= 16;
	  PP -= coutExpert;
	  blank() << "Suppression de l'expertise martiale pour "
		  << ListeArmes -> at( choixPreExistant )
		  << endmsg;
	}
      CompetenceEtNiveau[ indexes[ choix - 1 ] ] += 16;
      if ( pred == choix - 1 )
	PP -= coutExpert - 1;
      else
	PP -= coutExpert;
      blank() << "Ajout de l'expertise martiale pour "
	      << ListeArmes -> at( indexes[ choix - 1 ] )
	      << endmsg;
      
      for ( mapIt = mapBegin; mapIt != mapEnd; mapIt++, indice++ )
	{
	  it = find( Begin, End, mapIt -> first );
	  if ( *(it + 1) != mapIt -> second )
	    {
	      linfo() << ListeArmes -> at( *it ) << " : "
		      << *(it + 1) << " -> " << mapIt -> second
		      << endmsg;
	      *(it + 1) = mapIt -> second;
	    }
	}
    }

  unsigned nbrSpecialisation( aSpecialisation() );

  if ( nbrSpecialisation == 0 )
    {
      info() << "Ne peut pas avoir de spécialisation" << endmsg;
      func() << "Joueur::augmenterCompMartiales -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      return;
    }
  
  unsigned coutSpec( prixSpecialisation() );

  for ( mapIt = mapBegin, indice = 1, choixPreExistant = -1u;
	mapIt != mapEnd; mapIt++, indice++ )
    {
      blank() << indice << ' ' << ListeArmes -> at( mapIt -> first );
      if ( ( mapIt -> second & 7 ) > 0 )
	{
	  choixPreExistant = indice - 1;
	  blank() << " (choix actuel)";
	}
      if ( ( mapIt -> second & 8 ) >> 3 == 1 )
	blank() << " (arme de prédilection)";
      if ( ( mapIt -> second & 16 ) >> 3 == 1 )
	blank() << " (expertise)";
      blank() << endmsg;
    }
  blank() << ++indice
	  << " Aucune (ou conserver le choix actuel)" << endmsg;

  if ( nbrSpecialisation == 1 && choixPreExistant != -1u && PP < 2 * coutSpec )
    {
      warning() << "Pas assez de PP" << endmsg;
      func() << "Joueur::augmenterCompMartiales -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      return;
    }
  else if ( nbrSpecialisation == 1 && PP < coutSpec )
    {
      warning() << "Pas assez de PP" << endmsg;
      func() << "Joueur::augmenterCompMartiales -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      return;
    }
  else if ( nbrSpecialisation == 2 && PP < coutSpec )
    {
      warning() << "Pas assez de PP" << endmsg;
      func() << "Joueur::augmenterCompMartiales -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      return;
    }

  func() << "Joueur::augmenterCompMartiales -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Permet la progression en XP du personnage. Le nombre de point
 * d'expérience est augmenté de la manière suivante :\n
 * \e 1 si le personnage n'a qu'une classe le nombre de XP de cette
 * dernière est mis à jour.\n
 * \e 2 si le personnage est multiclassé, le nombre de XP de chaque
 * classe est mis à jour (avec la fraction de XP appropriée).\n
 * \e 3 si le personnage a jumelé, le nombre de XP de la \e dernière
 * classe est mis à jour.
 *
 * Dans chaque cas, on regarde ensuite s'il y a eu passage de niveau.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e INFO permet d'afficher une phrase lors d'un passage de niveau\n
 * \e FUNC  permet d'afficher le nombre d'xp avant - après\n
 * \e DEBUG permet d'afficher l'état multi / jumelé / single classe\n
 *
 * @param[in] xp nombre de XP a distribuer.
 *
 * @return StatusCode, dont la variable Etat contient \e true s'il y a
 * eu passage de niveau, auquel cas la variable Valeur contient le
 * numéro de la classe qui a progressé.
 *
 *****************************************************************************/
StatusCode Joueur::ajouterXP(const unsigned& xp)
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::ajouterXP -> début" << endmsg;

  bool lvlUp( false );

  unsigned a_distribuer, tmp_niv, quelleClasse(0);
  debug() << "nb_classes = " << nb_classes << endmsg;
  switch(TM_switch)
    {
    case Non:
      func() << "Pas de classes multiples" << endmsg;
      func() << "Avant : " << J_classe.back() -> xp() << endmsg;
      tmp_niv = J_classe.back() -> niveau();
      a_distribuer = xp;
      J_classe.back() -> augmenterXP(a_distribuer);
      if (tmp_niv != J_classe.back() -> niveau())
	{
	  info() << "Tu passes un niveau!" << endmsg;
	  lvlUp = true;
	  J_classe.back() -> augmenterTalents( J_race -> type(), Traits );
	}
      debug() << "Après : " << J_classe.back() -> xp() << endmsg;
      break;
    case Mul:
      func() << "Perso multiclassé" << endmsg;
      debug() << "Avant : " << J_classe.back() -> xp() << endmsg;      
      a_distribuer = xp / nb_classes;
      for (unsigned i(0); i < nb_classes; i++)
	{
	  tmp_niv = J_classe[i] -> niveau();
	  J_classe[i] -> augmenterXP(a_distribuer);
	  if (tmp_niv != J_classe[i] -> niveau())
	    {
	      info() << "Tu passes un niveau de "
		     << J_classe[i] -> classe() <<"!" << endmsg;
	      lvlUp = true;
	      quelleClasse = i;

	      J_classe[i] -> augmenterTalents( J_race -> type(), Traits );
	    }
	}
      debug() << "Après : " << J_classe.back() -> xp() << endmsg;
      break;
    case Jum:
      func() << "Perso à classes jumelées" << endmsg;
      debug() << "Avant : " << J_classe.back() -> xp() << endmsg;
      tmp_niv = J_classe.back() -> niveau();
      a_distribuer = xp;
      J_classe.back() -> augmenterXP(a_distribuer);
      if (tmp_niv != J_classe.back() -> niveau())
	{
	  info() << "Tu passes un niveau!" << endmsg;
	  lvlUp = true;
	  J_classe.back() -> augmenterTalents( J_race -> type(), Traits );
	}
      debug() << "Après : " << J_classe.back() -> xp() << endmsg;
      break;
    default:
      error() << "TypeMulti inconnu dans Joueur::ajouterXP" << endmsg;
    }

  func() << "Joueur::ajouterXP -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);

  return StatusCode( lvlUp, quelleClasse );
}

/**************************************************************************//**
 *
 * Permet la progression en PP du personnage. Le nombre de PP est
 * augmenté de la valeur donnée.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e INFO permet d'afficher le nombre de pp avant - après\n
 * \e FUNC  permet d'afficher les message de début et fin
 *
 * @param[in] pp nombre de PP a ajouter au total.
 *
 *****************************************************************************/
void Joueur::ajouterPP(const unsigned& pp)
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::ajouterPP -> début" << endmsg;
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(interne);
  info() << "Avant : " << PP << endmsg;
  PP += pp;
  info() << "Après : " << PP << endmsg;
  func() << "Joueur::ajouterPP -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Permet la progression en PV du personnage. Le nombre de PV est
 * augmenté de la valeur donnée.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e INFO permet d'afficher le nombre de pp avant - après\n
 * \e FUNC  permet d'afficher les message de début et fin
 *
 * @param[in] pv nombre de PV a ajouter au total.
 *
 *****************************************************************************/
void Joueur::ajouterPV(const unsigned& pv)
{
  /*Debug::*/empileNiveau( &interne );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(interne);
  func() << "Avant : " << PV << endmsg;
  PV += pv;
  func() << "Après : " << PV << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Permet d'ajuster le nbr de PP à la création, d'après le score
 * d'Intelligence du PJ. La valeur du nombre de PP disponible est
 * directement modifiée.
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e INFO permet d'afficher le changement.\n
 * \e FUNC permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::modificateurPP()
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::modificateurPP -> début" << endmsg;
  info() << "PPs avant : " << PP << endmsg;
  switch( Traits[ 3 ]/*J_classe[0] -> trait(3)*/)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
      PP += 1;
      break;
    case 9:
    case 10:
    case 11:
      PP += 2;
      break;
    case 12:
    case 13:
      PP += 3;
      break;
    case 14:
    case 15:
      PP += 4;
      break;
    case 16:
    case 17:
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
      PP += Traits[ 3 ]/*J_classe[0] -> trait(3)*/ - 11;
      break;
    case 24:
      PP += 15;
      break;
    case 25:
      PP += 20;
      break;
    }

  info() << "PPs après : " << PP << endmsg;
  func() << "Joueur::modificateurPP -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Permet d'ajuster le valeur d'une compétence non martiale lors de la
 * sélection de celle-ci. On déduit l'ajustement de la valeur du
 * meilleur trait associé (càd le plus avantageux pour le PJ), puis on
 * modifie le score de la compétence.\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e DEBUG permet d'afficher la valeur du trait correspondant\n
 * \e FUNC  permet d'afficher les messages de début et de fin\n
 * \e INFO  permet d'afficher le changement
 *
 * @param[in,out] val score de la compétence à modifier.
 * @param[in] trait valeur du trait associé, qui détermine l'ajustement.
 *
 *****************************************************************************/

void Joueur::modificateurVal(unsigned& val, const unsigned& trait) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::modificateurVal -> début" << endmsg;
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(interne);
  debug() << "Trait numéo " << trait << endmsg;
  info()  << "Valeur avant : " << val << endmsg;
  switch(trait)
    {
    case 1:
    case 2:
    case 3:
      val -= 5;
      break;
    case 4:
      val -= 4;
      break;
    case 5:
      val -= 3;
      break;
    case 6:
      val -= 2;
      break;
    case 7:
      val -= 1;
      break;
    case 8:
    case 9:
    case 10:
    case 11:
    case 12:
    case 13:
      break;
    case 14:
      val += 1;
      break;
    case 15:
      val += 2;
      break;
    case 16:
      val += 3;
      break;
    case 17:
      val += 4;
      break;
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
    case 24:
    case 25:
      val += 5;
    }
  info()  << "Valeur après : " << val << endmsg;
  func() << "Joueur::modificateurVal -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Retranscrit le nom sans espace ni apostrophes. Cette chaîne de
 * caractère est utilisée pour créer le répertoire dans le dossier
 * Feuilles/.
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e INFO permet d'afficher le résultat de la conversion
 * \e FUNC permet d'afficher les messages de début et de fin
 *
 * @return le nom du personnage sans espace ni apostrohes.
 *
 *****************************************************************************/

string Joueur::convertNom() const
{
  /*Debug::*/empileNiveau( &interne );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(interne);
  func() << "Joueur::convertNom -> début" << endmsg;

  string retour(Nom);
  size_t loc(retour.find("\\ "));

  while(loc != string::npos)
    {
      retour.replace(loc, 2, "");
      loc = retour.find("\\ ");
    }

  loc = retour.find(" ");
  while(loc != string::npos)
    {
      retour.replace(loc, 1, "");
      loc = retour.find(" ");
    }

  loc = retour.find("\\'");
  while(loc != string::npos)
    {
      retour.replace(loc, 2, "");
      loc = retour.find("\\'");
    }

  loc = retour.find("\'");
  while(loc != string::npos)
    {
      retour.replace(loc, 1, "");
      loc = retour.find("\'");
    }

  info() << Nom << " -> " << retour << endmsg;

  func() << "Joueur::convertNom -> fin" << endmsg;
  /*Debug::*/depileNiveau();

  return retour;
}

/**************************************************************************//**
 *
 * Calcule le coût en PP pour prendre une arme de prédilection. Les
 * combattant l'ont pour 2 PP, les prêtres et roublards pour 3 et les
 * magiciens pour 4.
 *
 * @return le coût en PP.
 * 
 ******************************************************************************/
unsigned Joueur::prixArmePredilection() const
{
  vector< Classe* >::const_iterator it, End( J_classe.end() );

  unsigned coutSimple( 10 );
  
  for ( it = J_classe.begin(); it != End; it++ )
    {
      switch( (*it) -> tc() -> front() )
	{
	case Combattants:
	  coutSimple = 2;
	  break;
	case Pretres:
	case Roublards:
	  if ( coutSimple > 3 )
	    coutSimple = 3;
	  break;
	case Magiciens:
	  if ( coutSimple > 4 )
	    coutSimple = 4;
	  break;
	default:
	  warning() << "TypeClasse inconnu : "
		    << unsigned( (*it) -> tc() -> front() )
		    << endmsg;
	}
    }

  return coutSimple;
}

/**************************************************************************//**
 *
 * Calcule le coût en PP pour prendre une expertise martiale. Les
 * combattant l'ont pour 2 PP, les prêtres et roublards pour 4 et les
 * magiciens pour 5. Une réduction de 1 PP est accordée si l'arme choisie est
 * déjà l'arme de prédilection du personnage. Cette réduction n'est toutefois
 * pas appliquée ici.
 *
 * @return le coût en PP.
 * 
 ******************************************************************************/
unsigned Joueur::prixExpertiseMartiale() const
{
  vector< Classe* >::const_iterator it, End( J_classe.end() );

  unsigned coutSimple( 10 );
  
  for ( it = J_classe.begin(); it != End; it++ )
    {
      switch( (*it) -> tc() -> front() )
	{
	case Combattants:
	  coutSimple = 2;
	  break;
	case Pretres:
	case Roublards:
	  if ( coutSimple > 4 )
	    coutSimple = 4;
	  break;
	case Magiciens:
	  if ( coutSimple > 5 )
	    coutSimple = 5;
	  break;
	default:
	  warning() << "TypeClasse inconnu : "
		    << unsigned( (*it) -> tc() -> front() )
		    << endmsg;
	}
    }

  return coutSimple;  
}

/**************************************************************************//**
 *
 * Permet d'accéder au prix d'uns spécialisation martiale. Les
 * guerriers peuvent prendre une spécialisation pour 2 pp dès le
 * niveau 1. Les guerriers multiclassés doivent attendre le niveau 2
 * et dépenser 4 pp. Les rôdeurs et paladins peuvent se spécialiser
 * pour un coût de 4 pp dès le niveau 3. Les prêtres attendent le
 * niveau 5 et dépensent 6 pp. Les roublards dépensent 8 pp et
 * attendent le niveau 6. Finalement, les magiciens peuvent prendre
 * une spécialisation dès le niveau 7, pour un coût de 10 pp.
 *
 * @return le coût en pp de la spécialisation pour le personnage, ou
 * le nombre \c -1u si le personnage ne peut se spécialiser.
 *
 *****************************************************************************/
unsigned Joueur::prixSpecialisation() const
{
  if ( nbrClasses() == 1 && J_classe.front() -> classe() == "Guerrier" )
    return 2;
  else if ( nbrClasses() > 1 )
    {
       vector< Classe* >::const_iterator it, End( J_classe.end() );

       for ( it = J_classe.begin(); it != End; it++ )
	 {
	   if ( (*it) -> classe() == "Guerrier" && (*it) -> niveau() >= 2 )
	     return 4;
	 }
    }

  if ( nbrClasses() == 1 && ( J_classe.front() -> classe() == "Rôdeur" ||
			      J_classe.front() -> classe() == "Paladin" ) &&
       J_classe.front() -> niveau() >= 3 )
    return 4;
  else if ( nbrClasses() == 1 && ( J_classe.front() -> classe() == "Clerc" ||
				   J_classe.front() -> classe() == "Druide" ) &&
	    J_classe.front() -> niveau() >= 5 )
    return 6;
  else if ( nbrClasses() == 1 && ( J_classe.front() -> classe() == "Barde" ||
				   J_classe.front() -> classe() == "Voleur" ) &&
	    J_classe.front() -> niveau() >= 6 )
    return 8;
  else if ( nbrClasses() == 1 && ( J_classe.front() -> classe() == "Mage" ||
				   J_classe.front() -> classe() == "Spécialiste" ) &&
	    J_classe.front() -> niveau() >= 7 )
    return 10;
  
  return -1u;
}

/**************************************************************************//**
 *
 * Enlève les doublons dans J_CompAccess, en faisant appel aux
 * fonctions sort et unique de la STL.
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC permet d'afficher les messages de fin et de début de
 * fonction
 *
 *****************************************************************************/
void Joueur::nettoieTC()
{
  /*Debug::*/empileNiveau( &interne );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(interne);

  func() << "Joueur::nettoieTC -> début" << endmsg;

  vector<TypeClasse>::iterator it, Begin(J_CompAccess.begin()),
    End(J_CompAccess.end());

  sort(Begin, End);

  it = unique(Begin, End);

  J_CompAccess.erase( it, End );

  func() << "Joueur::nettoieTC -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/***************************************************************************//**
 *
 * Permet de calculer le score associé de chaque compétence diverse
 * donnée en argument. La méthode prend en premier lieu la valeur de
 * base de la compétence, puis modifie cette valeur avec l'éventuel
 * ajustement dû aux traits associés. Si deux traits sont associés à
 * une compétence, le trait maximal est prit en compte.\n
 *
 * Le niveau de sortie est paramétré par Joueur::intenr :\n
 * \e FUNC  affiche les messages de début et de fin de méthode.\n
 * \e LFUNC affiche pour chaque compétence le nom, la valeur de base
 * et l'ajustement.
 *
 * @param[in] numeros conteneur des numéros des compétences
 * sélectionnées.
 * @param[out] comp conteneur des compétences avec leurs scores
 * associés, la structure est Compétence - Valeur. Est écrit par la
 * méthode.
 *
 *****************************************************************************/
void Joueur::gererDiverses( const vector<unsigned>& numeros,
			    vector<unsigned>& comp ) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::gererDiverses -> début" << endmsg;
  
  comp.clear();

  unsigned i, nbr( numeros.size() ), quelle, trait1, trait2, mod;

  for ( i = 0; i < nbr; i++ )
    {
      quelle = numeros[i];
      comp.push_back( quelle );
      comp.push_back( CompetencesDiverses.at( quelle ).valeurBase() );
      trait1 = CompetencesDiverses.at( quelle ).traitBonus( 0 );
      trait2 = CompetencesDiverses.at( quelle ).traitBonus( 1 );
      if ( trait1 == 255 && trait2 == 255 )
	continue;
      else if ( trait1 != 255 && trait2 != 255 )
	{
	  mod = max( Traits[ trait1 ], Traits[ trait2 ] );
	}
      else if ( trait1 != 255 )
	mod = Traits[ trait1 ];
      lfunc() << "Compétence : " << CompetencesDiverses.at( quelle ).nom()
	      << ", valeur de base : " << comp.back()
	      << ", ajustement : " << mod << endmsg;
      modificateurVal( comp.back(), mod );
    }

  func() << "Joueur::gererDiverses -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Permet de transformer une simple liste de compétence martiales
 * (données par leur numéros) en une liste comprenant le numéro de la
 * compétence suivi du niveau de compétence.
 *
 * @param[in] numeros conteneur des numéros des compétences
 * sélectionnées.
 * @param[out] comp conteneur des compétences avec leurs scores
 * associés, la structure est Compétence - Niveau. Est écrit par la
 * méthode.
 *****************************************************************************/
void Joueur::gererMartiales(const vector< unsigned >& numeros,
			    vector< unsigned >& comp) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::gererMartiales -> début" << endmsg;

  unsigned i, tailleNum( numeros.size() );

  comp.assign( tailleNum * 2, 0 );

  for ( i = 0; i < tailleNum; i++ )
    comp[ 2 * i ] = numeros[i];

  func() << "Joueur::gererMartiales -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Ecrit les traits et les ajustements correspondant.\n
 * 
 * L'astuce est d'ouvrir un chablon et de lire les informations
 * contenues dans ce chablon. Ce dernier contient un '#' à chaque fois
 * qu'une valeur doit être entrée.\n
 *
 * Ici nous allons éditer Feuilles/\e Nom/traits.inc.tex.\n
 *
 * La variable Joueur::fonction_tex permet d'afficher les informations
 * suivantes :\n
 * \e INFO  permet d'afficher le fichier que l'on édite
 * \e DEBUG permet d'afficher le score de Force (pr la gestion de
 * For. Exc.), ainsi que l'état d'ouverture du fichier.
 *
 *****************************************************************************/
void Joueur::ecrireTraitsTex() const
{
  /*Debug::*/empileNiveau( &fonction_tex );
  func() << "Joueur::ecrireTraitsTex() -> début" << endmsg;
  /*
   * Alors le truc c'est ouvrir un chablon et lire les infos dedans
   * dans le chablon mettre un flag, genre '#' qui indique l'insertion d'une
   * donnée
   * ici on édite Feuilles/Nom/traits.inc.tex
   * Le chablon est dans Joueur0/
   */
  ifstream entree;
  ofstream sortie;
  string nom_fichier("Feuilles/"), ligne, str[33];
  bool for_ex(false);
  unsigned i, exept(0);
  size_t loc;

  for (i = 0; i < nb_classes; i++)
    {
      for_ex = J_classe[i] -> forceExceptionnelle( Traits[ 0 ] );
      if ( for_ex )
	{
	  break;
	  exept = Traits[ 6 ];
	}
      // if (J_classe[i] -> trait(0) == 18)
      // 	{
      // 	  if (J_classe[i] -> classe() == "Guerrier")
      // 	    {
      // 	      for_ex = true;
      // 	      exept = J_classe[i] -> trait(6);
      // 	      break;
      // 	    }
      // 	  else if (J_classe[i] -> classe() == "Clerc")
      // 	    {
      // 	      unsigned taille(J_classe[i] -> tailleCompetences());
      // 	      for (unsigned j(0); j < taille; j++)
      // 		{
      // 		  if (J_classe[i] -> numCompetence(j) == 38)
      // 		    {
      // 		      for_ex = true;
      // 		      exept = J_classe[i] -> trait(6);
      // 		      break;
      // 		    }
      // 		}
      // 	    }
      // 	}
    }
  str[0] = Nom;
  loc = str[0].find("\\'");
  if (loc != string::npos)
    str[0].replace(loc, 2, "'");
  if (for_ex)
    str[1] = "$18^{" + ecrireString(exept) + "}$";
  else
    str[1] = "$" + ecrireString( Traits[ 0 ] ) + "$";

  debug() << "Force " << Traits[ 0 ] << " -> " << str[1]  << endmsg;

  for (i = 1; i < 6; i++)
    str[i+1] = "$" + ecrireString( Traits[ i ] ) + "$";

  for (i = 1; i < 7; i++)
    {
      if (str[i].size() < 4)
	str[i].replace(0, 1, "$\\phantom{0}");
    }

  unsigned tmp_trait, tmp;
  if ( ! for_ex )
    {
      tmp =  Traits[ 0 ] - 1;
    }
  else
    {
      tmp_trait =  Traits[ 6 ];
      if ( tmp_trait <= 50 )
	tmp = 25;
      else if ( tmp_trait <= 75 )
	tmp = 26;
      else if ( tmp_trait <= 90 )
	tmp = 27;
      else if ( tmp_trait <= 99 )
	tmp = 28;
      else
	tmp = 29;
    }
  for (i = 0; i < 6; i++)
    str[7+i] = Aj_Force[tmp][i];

  tmp_trait =  Traits[ 1 ];

  if (tmp_trait < 7)
    tmp = tmp_trait -1;
  else if (tmp_trait < 15)
    tmp = 6;
  else if (tmp_trait < 19)
    tmp = tmp_trait - 8;
  else if (tmp_trait < 21)
    tmp = 11;
  else if (tmp_trait < 24)
    tmp = 12;
  else
    tmp = 13;
  for (i = 0; i < 3; i++)
    str[13+i] = Aj_Dexterite[tmp][i];

  tmp =  Traits[ 2 ] - 1;
  for (i = 0; i < 5; i++)
    str[16+i] = Aj_Const[tmp][i];

  tmp_trait =  Traits[ 3 ];
  if (tmp_trait < 2)
    tmp = tmp_trait - 1;
  else if (tmp_trait < 9)
    tmp = 1;
  else
    tmp = tmp_trait - 7;

  for (i = 0; i < 5; i++)
    str[21+i] = Aj_Int[tmp][i];
  
  tmp_trait =  Traits[ 4 ];
  if (tmp_trait < 14)
    tmp = tmp_trait - 1;
  else
    tmp = tmp_trait - 2;

  for (i = 0; i < 4; i++)
    str[26+i] = Aj_Sagesse[tmp][i];

  tmp_trait =  Traits[ 5 ];
  if (tmp_trait < 10)
    tmp = tmp_trait - 1;
  else if (tmp_trait < 13)
    tmp = 8;
  else
    tmp = tmp_trait - 3;
  for (i = 0; i < 3; i++)
    str[30+i] = Aj_Charisme[tmp][i];      

  entree.open("Joueur0/traits0.inc.tex");

  nom_fichier += convertNom();
  nom_fichier += "/traits.inc.tex";
  info() << "Ecriture de " << nom_fichier << endmsg;
  sortie.open(nom_fichier.c_str());
  debug() << "Etat ouverture fichier " << sortie.fail() << endmsg;

  i = 0;
  while(!entree.eof())
    {
      getline(entree, ligne);
      if (ligne[0] != '#')
	sortie << ligne << endl;
      else
	{
	  debug() << i << " -> " << str[i] << endmsg;
	  sortie << str[i];
	  i++;
	}
    }
  entree.close();
  sortie.close();
  func() << "Joueur::ecrireTraitsTex -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit la table des JS du Joueur.
 * Gère les classes multiples en prenant le JS le plus bas.\n
 * 
 * Alors le truc c'est ouvrir un chablon et lire les infos dedans dans
 * le chablon mettre un flag, genre '#' qui indique l'insertion d'une
 * donnée.\n
 *
 * Ici on édite  Feuilles/\e Nom /JS.inc.tex.\n
 *
 * La variable Joueur::fonction_tex permet d'afficher les informations
 * suivantes :\n
 * \e INFO  permet d'afficher le fichier que l'on édite\n
 * \e FUNC messages de début et fin de méthode\n
 * \e LFUNC permet d'afficher les différents JS, dans l'ordre, de
 * chaque Classe ainsi que les JS finaux\n
 * 
 *****************************************************************************/
void Joueur::ecrireJSTex() const
{
  /*Debug::*/empileNiveau( &fonction_tex );
  func() << "Joueur::ecrireJSTtex -> début" << endmsg;
  /*
   * Alors le truc c'est ouvrir un chablon et lire les infos dedans
   * dans le chablon mettre un flag, genre '#' qui indique l'insertion d'une
   * donnée
   * ici on édite Feuilles/Nom/JS.inc.tex
   * Le chablon est dans Joueur0/
   */
  ifstream entree;
  ofstream sortie;
  string nom_fichier("Feuilles/"), ligne, str[5];
  unsigned JS[5] = {20, 20, 20, 20, 20}, tmp_JS[5], *ptr(tmp_JS);
  unsigned i, combien, bonus(0);

  for (i = 0; i < nb_classes; i++)
    {
      J_classe[i] -> js(ptr);
      for (unsigned j(0); j < 5; j++)
	{
	  lfunc() << "JS[" << i << ',' << j << "] "<<tmp_JS[j] << endmsg;
	  if (tmp_JS[j] < JS[j])
	    JS[j] = *(tmp_JS + j);
	}
    }

  /*
   * On traite ici les races qui peuvent avoir un bonus aux JS
   */
  string race;
  bool poison(false), a_bonus(false);
  race = J_race -> type();
  combien = J_race -> tailleCapacites();

  debug() << "race = " << race << endmsg;

  if ( race == "Gnome" )
    a_bonus = ( J_race -> adresseCapacites() -> end() !=
		find( J_race -> adresseCapacites() -> begin(),
		      J_race -> adresseCapacites() -> end(), 3 ) );
  else if ( race == "Hobbit" )
    poison = a_bonus = ( J_race -> adresseCapacites() -> end() !=
			 find( J_race -> adresseCapacites() -> begin(),
			       J_race -> adresseCapacites() -> end(), 2 ) );
  else if ( race == "Nain" )
    poison = a_bonus = ( J_race -> adresseCapacites() -> end() !=
			 find( J_race -> adresseCapacites() -> begin(),
			       J_race -> adresseCapacites() -> end(), 1 ) );

  // for(i = 0; i < combien; i++)
  //   {
  //     if (race == "Gnome" && J_race -> numCapacite(i) == 3)
  // 	{
  // 	  func() << "Joueur::ecrireJSTtex -> bonus aux JS de gnome" << endmsg;
  // 	  a_bonus = true;
  // 	  break;
  // 	}
  //     else if (race == "Hobbit" && J_race -> numCapacite(i) == 2)
  // 	{
  // 	  func() << "Joueur::ecrireJSTtex -> bonus aux JS de hobbit" << endmsg;
  // 	  a_bonus = true;
  // 	  poison = true;
  // 	  break;
  // 	}
  //     else if (race == "Nain" && J_race -> numCapacite(i) == 1)
  // 	{
  // 	  func() << "Joueur::ecrireJSTtex -> bonus aux JS de nain" << endmsg;
  // 	  a_bonus = true;
  // 	  poison = true;
  // 	  break;
  // 	}
  //   }

  if (a_bonus)
    {
      switch( Traits[ 2 ] )
	{
	case 4:
	case 5:
	case 6:
	  bonus = 1;
	  break;
	case 7:
	case 8:
	case 9:
	case 10:
	  bonus = 2;
	  break;
	case 11:
	case 12:
	case 13:
	  bonus = 3;
	  break;
	case 14:
	case 15:
	case 16:
	case 17:
	  bonus = 4;
	  break;
	case 18:
	case 19:
	case 20:
	  bonus = 5;
	  break;
	default:
	  bonus = 0;
	}
      JS[1] -= bonus;
      JS[4] -= bonus;
    }

  for (i = 0; i < 5; i++)
    {
      if (i == 0 && poison)
	str[i] = "$" + ecrireString(JS[i]) + " (" + ecrireString(JS[i] - bonus) + ")$";
      else
	str[i] = "$" + ecrireString(JS[i]) + "$";
    }

  entree.open("Joueur0/JS0.inc.tex");


  nom_fichier += convertNom();
  nom_fichier += "/JS.inc.tex";
  info() << "Ecriture de " << nom_fichier << endmsg;
  sortie.open(nom_fichier.c_str());

  i = 0;
  while(!entree.eof())
    {
      getline(entree, ligne);
      if (ligne[0] != '#')
	sortie << ligne << endl;
      else
	{
	  linfo() << i << " -> " << str[i] << endmsg;
	  sortie << str[i];
	  i++;
	}
    }
  sortie.close();
  entree.close();
  func() << "Joueur::ecrireJSTtex -> fin" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit le nbr de PV, le TAc0 et la CA
 *
 * Le niveau de sortie est paramétré par Joueur::fonction_tex :\n
 * \e INFO  affiche le fichier que l'on édite.\n
 * \e FUNC  affiche les messages de début et de fin de méthode.\n
 * \e DEBUG affiche ces trois nombres.
 *
 *****************************************************************************/
void Joueur::ecrireScoresTex() const
{
  /*Debug::*/empileNiveau( &fonction_tex );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(fonction_tex);
  func() << "Joueur::ecrireScoresTex -> début" << endmsg;
  ifstream entree;
  ofstream sortie;
  string nom_fichier("Feuilles/"), ligne, str[6];
  unsigned i, total( 0 );

  str[0] = "$" + ecrireString( PV ) + "$";
  str[1] = "$" + ecrireString( TAc0 ) + "$";
  str[2] = "$" + ecrireString( CA ) + "$";
  str[3] = "$" + ecrireString( PP ) + "$";
  str[4] = "$" + ecrireString( J_classe.back() -> xp() ) + "$";
  debug() << "XP : " << J_classe.back() -> xp()
	  << " -> " << ecrireString(J_classe.back() -> xp()) << endmsg;

  switch(TM_switch)
    {
    case Mul:
      str[5] = "$"+ecrireString(nb_classes * J_classe.back() -> xp())+"$";
      break;
    case Jum:
      for ( i = 0; i < nb_classes; i++ )
       	total += J_classe[ i ] -> xp();
      str[5] = "$" + ecrireString( total ) + "$";
      break;
    case Non:
      str[5] = str[4];
      break;
    }

  entree.open("Joueur0/scores0.inc.tex");

  nom_fichier += convertNom();
  nom_fichier += "/scores.inc.tex";
  info() << "Ecriture de " << nom_fichier << endmsg;
  sortie.open(nom_fichier.c_str());

  i = 0;
  while(!entree.eof())
    {
      getline(entree, ligne);
      if (ligne[0] != '#')
	sortie << ligne << endl;
      else
	{
	  debug() << i << " -> " << str[i] << endmsg;
	  sortie << str[i];
	  i++;
	}
    }
  sortie.close();
  entree.close();
  func() << "Joueur::ecrireScoresTex -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Ecrit la Race et les capacités raciales\n
 *
 * Le niveau de sortie est paramétré par Joueur::fonction_tex :\n
 * \e INFO  affiche le fichier que l'on édite.\n
 * \e FUNC affiche les messages de début et de fin de méthode, ainsi
 * que le nombre de capacités raciales.\n
 * \e DEBUG affiche ces capacités
 *
 *****************************************************************************/
void Joueur::ecrireRaceTex() const
{
  /*Debug::*/empileNiveau( &fonction_tex );
  func() << "Joueur::ecrireRaceTex -> début" << endmsg;
  ofstream sortie;
  string nom_fichier("Feuilles/");

  EcrireElementConteneur< string, ostream  > sortieStr( &sortie,
							"\\item [-] ", "\n" );

  unsigned taille( J_race -> tailleCapacites() );
  vector<string> str;
  //str.push_back("\\subsection*{"+J_race -> type()+"}");
  func() << "Nbr capa : " << taille << endmsg;

  for (unsigned i(0); i < taille; i++)
    {
      str.push_back( J_race -> nomCapacite(i)  );
      lfunc() << str[i] << endmsg;
    }

  nom_fichier += convertNom();
  nom_fichier += "/race.inc.tex";
  info() << "Ecriture de " << nom_fichier << endmsg;
  sortie.open(nom_fichier.c_str());

  sortie << "\\subsection*{"+J_race -> type()+"}" << endl;
  sortie << "\\begin{itemize}" << endl;
  for_each( str.begin(), str.end(), sortieStr );
  // for (unsigned i(0); i < taille; i++)
  //   sortie << "\\item [-] " << str[i+1] << endl;
  if (taille == 0)
    sortie << "\\item [] Aucune" << endl;
  sortie << "\\end{itemize}" << endl;
  
  sortie.close();
  func() << "Joueur::ecrireRaceTex -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Ecrit la Classe et les compétences de Classe.\n
 *
 * Le niveau de sortie est paramétré par Joueur::fonction_tex :\n
 * \e INFO  permet d'afficher le fichier que l'on édite.\n
 * \e FUNC  affiche les messages de début et de fin de méthode.\n
 * \e LINFO permet d'afficher le nombre de compétences, et si elle est
 * associée à un pourcentage.\n
 * \e LFUNC permet de savoir lesquelles on "saute".\n
 * \e DEBUG permet de toutes les afficher.
 *
 *****************************************************************************/
void Joueur::ecrireClasseTex() const
{
  /*Debug::*/empileNiveau( &fonction_tex );
  func() << "Joueur::ecrireClasseTex -> début" << endmsg;

  ofstream sortie;
  string nom_fichier("Feuilles/"), tmp;
  vector<string> str;
  bool override(false);

  EcrireElementConteneur< string, ostream  > sortieStr( &sortie,
							"\\item [-] ", "\n" );

  nom_fichier += convertNom();
  nom_fichier += "/classe.inc.tex";
  info() << "Ecriture de " << nom_fichier << endmsg;
  sortie.open(nom_fichier.c_str());

  for (unsigned i(0); i < nb_classes; i++)
    {
      str.clear();
      unsigned taille(J_classe[i] -> tailleCompetences());
      str.push_back("\\subsection*{"+J_classe[i] -> classe()+" (niveau $"+ecrireString(J_classe[i] -> niveau())+"$)}");
      linfo() << "Nbr comp : " << taille << endmsg;

      for (unsigned j(0); j < taille; j++)
	{
	  if (override)
	    {
	      override = false;
	      debug() << "On saute celui-là" << endmsg;
	      continue;
	    }
	  debug() << "ici j = " << j << endmsg;
	  tmp = J_classe[i] -> nomCompetence( j, J_race -> type(),
					      Traits, override, true );
	  debug() << tmp << endmsg;
	  if ( override )
	    lfunc() << "Pourcentage, attention!" << endmsg;
	  // if ( override )
	  //   {
	  //     lfunc() << "Pourcentage, attention!" << endmsg;
	  //     str.push_back(tmp);
	  //   }
	  // else
	  //   str.push_back(tmp);
	  str.push_back( tmp );
	}
      sortie << str[0] << endl;
      sortie << "\\begin{itemize}" << endl;
      for_each( ++str.begin(), str.end(), sortieStr );
      // taille = str.size();
      // for (unsigned j(1); j < taille; j++)
      // 	sortie << "\\item [-] " << str[j] << endl;
      sortie << "\\end{itemize}" << endl;
    }
  sortie.close();
  func() << "Joueur::ecrireClasseTex -> début" << endmsg;
  /*Debug::*/depileNiveau();
  //dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les désavantages, dons et compétences non martiales
 *
 * Le niveau de sortie est paramétré par Joueur::fonction_tex :\n
 * \e INFO  permet d'afficher le fichier que l'on édite.\n
 * \e FUNC permet d'afficher le nombre de compétences, et si elle est
 * associée à un pourcentage.\n
 * \e DEBUG permet de toutes les afficher, de savoir lesquelles on
 * "saute" ie celles qui ont un pourcentage associé.
 *
 *****************************************************************************/
void Joueur::ecrireCompTex() const
{
  /*Debug::*/empileNiveau( &fonction_tex );
  func() << "Joueur::ecrireCompTex -> début" << endmsg;
  ofstream sortie;
  string nom_fichier("Feuilles/"), tmp;
  vector<string> str;

  nom_fichier += convertNom();
  nom_fichier += "/comp.inc.tex";
  info() << "Ecriture de " << nom_fichier << endmsg;
  sortie.open( nom_fichier.c_str() );

  EcrireElementConteneur< string, ostream  > sortieStr( &sortie,
							"\\item [-] ", "\n" );
  LireNomAbstrait< CapaciteRaciale > Traducteur( &Desavantages );

  unsigned nbr, i;

  // On s'occupe des désavantages

  nbr = nbrDesavantages();

  if (nbr > 0)
    {
      sortie << "\\subsection*{Désavantages}" << endl << "\\begin{itemize}"
	     << endl;
      str.resize(nbr);
      

      transform( J_Desavantages.begin(), J_Desavantages.end(), str.begin(),
		 Traducteur );
      for_each( str.begin(), str.end(), sortieStr );
      
      sortie << "\\end{itemize}" << endl;
    }

  // On s'occupe ensuite des dons

  Traducteur.setAbstrait( &Dons );
  if (nbr > 0)
    {
      str.resize(nbr);
      sortie << "\\subsection*{Dons}" << endl << "\\begin{itemize}" << endl;
  
      transform( J_Dons.begin(), J_Dons.end(), str.begin(),
		 Traducteur );
      for_each( str.begin(), str.end(), sortieStr );

      sortie << "\\end{itemize}" << endl;
    }

  // On s'occupe ensuite des compétences diverses

  nbr = nbrCompetences();

  if (nbr > 0)
    {
      sortie << "\\subsection*{Compétences diverses}" << endl
	     << "\\begin{itemize}" << endl;
      
      for (i = 0; i < nbr; i+=2)
	{
	  sortie << "\\item [-] "
		 << "\\begin{tabular*}{12cm}{@{\\extracolsep{\\fill}}l r}"
		 << endl << CompetencesDiverses.at( J_CompDiv[i] ).nom()
		 << " & " << J_CompDiv[i+1] << endl << "\\end{tabular*}"
		 << endl;
	}
      
      sortie << "\\end{itemize}" << endl;
    }

  // On passe aux compétences martiales

  nbr = nbrCompMartiales();

  if ( nbr == 0 )
    {
      sortie.close();
      func() << "Joueur::ecrireCompTex -> fin" << endmsg;
      /*Debug::*/depileNiveau();
    }

  sortie << "\\subsection*{Compétences martiales}" << endl
	 << "\\begin{footnotesize}" << endl
	 << "\\tablefirsthead{%"
    	 << "Arme & Poids & Taille & Type & Init. & Tir &"
	 << " Portée & Dégâts PM & Dégâts G \\\\ \\hline}" << endl
	 << "\\tablehead{%"
    	 << "Arme & Poids & Taille & Type & Init. & Tir &"
	 << " Portée & Dégâts PM & Dégâts G \\\\ \\hline}" << endl
	 << "\\begin{supertabular*}{14cm}{@{\\extracolsep{\\fill}}"
	 << " l l l l l l l l l}" << endl;

  unsigned j(0), compteur(0);

  string vertEspace( "\\rule{0cm}{11pt}" );
  unsigned niveau;
  bool predil, expert;

  const vector< Martiale > * ListeArmes = LireArmesXML -> listeArmes();
  const Martiale * mart;
  
  for ( i = 0; i < nbr; i+=2 )
    {
      j = J_Martiales[i];
      niveau = J_Martiales[ i + 1 ] % 8;
      predil = J_Martiales[ i + 1 ] & 0x8;
      expert = J_Martiales[ i + 1 ] & 0x10;

      warning() << "compétence " << i << " est " << j << endmsg;
 
      do
	{
	  mart = &( ListeArmes -> at( j ) );
	  sortie << vertEspace << *mart << endl;
	  j++;
	}
      while ( ListeArmes -> at( j - 1 ) . afficherSuite() );

    }


  sortie << "\\end{supertabular*}" << endl << "\\end{footnotesize}" << endl;

  sortie.close();
  func() << "Joueur::ecrireCompTex -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**************************************************************************//**
 *
 * Ecrit les sorts du Livre de Sorts (pour un mage, barde) ou les
 * sorts des sphères accessibles (clerc, druide, rôdeur, paladin).\n
 *
 * Pour un Joueur à Classe multiple, le .tex contient les informations
 * des deux classes concaténées.\n
 *
 * Le niveau de sortie est paramétré par Joueur::fonction_tex :\n
 * \e INFO  permer d'afficher le fichier que l'on édite.\n
 * \e FUNC  affiche les messages de début et de fin de méthode.\n
 * \e DEBUG permet d'afficher la classe courante.
 *
 *****************************************************************************/
void Joueur::ecrireSortsTex() const
{
  /*Debug::*/empileNiveau( &fonction_tex );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(fonction_tex);
  func() << "Joueur::ecrireSortsTex -> début" << endmsg;
  string nom_fichier;
  bool ecraser;
  for (unsigned i(0); i < nb_classes; i++)
    {
      ecraser = (i == 0);
      nom_fichier = "Feuilles/" + convertNom() + "/sorts.inc.tex";
      //fichier = "sorts.inc.tex";
      info() << "Ecriture de " << nom_fichier << endmsg;
      debug() << J_classe[i] -> classe() << endmsg;
      J_classe[i] -> ecrireSorts(nom_fichier, ecraser);
    }
  func() << "Joueur::ecrireSortsTex -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/***************************************************************************//**
 *
 * Permet de construire un personnage à partir d'information lues
 * depuis un fichier XML. Est utilisé par le constructeur
 * Joueur::Joueur, càd lors du chargement d'un PJ en mode console,
 * ainsi que lors du chargement d'un PJ en mode graphique (dans ce
 * cas, l'appel est plus explicite).\n
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC  affiche les messages de début et de fin de méthode.\n
 * \e LINFO affiche les différentes informations recueillies.
 *
 * @param[in] infoXML table associative contenant les information
 * extraites du xml, les clefs étant les balises XML. Un '+' est
 * ajouté à la balise si elle se répète (càd si un PJ a deux classe,
 * la première est indexée par "Classe", la seconde par "Classe+").
 *
 ******************************************************************************/
void Joueur::construitJoueur( map< string, string >* infoXML )
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::construitJoueur -> début" << endmsg;
  
  string valeur, elementValeur;

  vector< unsigned> vecUInt;

  // Premièrement on s'occupe de la race.

  Nom = infoXML -> operator[]("Nom");

  linfo() << "Nom : " << Nom << endmsg;

  string type( infoXML -> operator[]("Race") );

  linfo() << "Race : " << type << endmsg;

  valeur = infoXML -> operator[]("Capacites");

  if ( !lireVectorUInt( valeur, &vecUInt ) )
    {
      error() << "Ne peut pas lire les capacitées raciales" << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  else
    linfo() << "Compétences raciales : " << valeur << endmsg;

  if (type == "Humain")
    J_race = new Humain( vecUInt );
  else if (type == "Demi-Elfe")
    J_race = new DemiElfe( vecUInt );
  else if (type == "Demi-Ogre")
    J_race = new DemiOgre( vecUInt );
  else if (type == "Demi-Orque")
    J_race = new DemiOrque( vecUInt );
  else if (type == "Elfe")
    J_race = new Elfe( vecUInt );
  else if (type == "Gnome")
    J_race = new Gnome( vecUInt );
  else if (type == "Hobbit")
    J_race = new Hobbit( vecUInt );
  else if (type == "Nain")
    J_race = new Nain( vecUInt );
  else
    {
      error() << "Race inconnue : " << type << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }

  // OK, maintenant on va s'occuper de la (des) classe(s)
  unsigned  i, xp, nbClasses, compteur(0), nbSorts;
  vector< unsigned > traits;

  vector<Sort> vecSorts;

  valeur = infoXML -> operator[]( "Multi" );

  if ( !lireString( valeur, nbClasses ) )
    {
      error() << "Ne peut pas lire le nombre de classes" << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  else
    linfo() << "Nbr de classe(s) : " << valeur << endmsg;

  nb_classes = nbClasses;

  if ( nb_classes == 0 )
    TM_switch = Non;
  else
    {
      if ( J_race -> type() == "Humain" )
	TM_switch = Jum;
      else
	TM_switch = Mul;
    }

  valeur = infoXML -> operator[]( "Traits" );

  if ( !lireVectorUInt( valeur, &vecUInt ) )
    {
      error() << "Ne peut pas lire les traits" << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  else
    linfo() << "Traits : " << valeur << endmsg;
  
  traits.assign( vecUInt.begin(), vecUInt.end() );

  string tagClasse("Classe"), tagXP("XP"), tagComp("Competences"),
    tagSorts("Sorts");

  do
    {
      type = infoXML -> operator[]( tagClasse );

      linfo() << "Classe : " << type << " en posision " << compteur
	      << endmsg;

      valeur = infoXML -> operator[]( tagXP );

      if ( ! lireString( valeur, xp ) )
	{
	  error() << "Ne peut pas lire le nombre de XP" << endmsg;

	  func() << "Joueur::construitJoueur -> fin" << endmsg;
	  /*Debug::*/depileNiveau();
	  exit( 1 );
	}
      else
	linfo() << "Nombre de XP : " << xp << endmsg;

      if (type == "Guerrier")
	J_classe . push_back( new Guerrier( xp ) );
      else if (type == "Paladin")
	J_classe . push_back( new Paladin( xp ) );
      else if (type == "Rôdeur")
	J_classe . push_back( new Rodeur( xp ) );
      else if (type == "Clerc")
	J_classe . push_back( new Clerc( xp ) );
      else if (type == "Druide")
	J_classe . push_back( new Druide( xp ) );
      else if (type == "Mage")
	J_classe . push_back( new Mage( xp ) );
      else if (type == "Spécialiste")
	J_classe . push_back( new Specialiste( xp ) );
      else if (type == "Barde")
	J_classe . push_back( new Barde( xp ) );
      else if (type == "Voleur")
	J_classe . push_back( new Voleur( xp ) );
      else
	{
	  error() << "Classe inconnue" << type << endmsg;
	  func() << "Joueur::construitJoueur -> fin" << endmsg;
	  /*Debug::*/depileNiveau();
	  exit(1);
	}

      linfo() << "Classe OK" << endmsg;

      valeur = infoXML -> operator[]( tagComp );

      if ( !lireVectorUInt( valeur, &vecUInt ) )
	{
	  error() << "Ne peut pas lire les compétences" << endmsg;

	  func() << "Joueur::construitJoueur -> fin" << endmsg;
	  /*Debug::*/depileNiveau();
	  exit(1);
	}
      else
	linfo() << "Compétences de classe : " << valeur << endmsg;

      J_classe[ compteur ] -> setCompetences( vecUInt );

      linfo() << "Compétences OK" << endmsg;

      if ( infoXML -> find( tagSorts ) != infoXML -> end() )
	{
	  valeur = infoXML -> operator[]( tagSorts );

	  if ( !lireVectorUInt( valeur, &vecUInt ) )
	    {
	      error() << "Ne peut pas lire les sorts" << endmsg;

	      func() << "Joueur::construitJoueur -> fin" << endmsg;
	      /*Debug::*/depileNiveau();
	      exit(1);
	    }
	  else
	    linfo() << "Sorts : " << valeur << endmsg;

	  nbSorts = vecUInt . size();
	  
	  for (i = 0; i < nbSorts; i += 3)
	    {
	      vecSorts.push_back( Sort( vecUInt[i], vecUInt[i + 1],
					vecUInt[i + 2]) );
	    }
	  
	  J_classe[ compteur ] -> setSorts( vecSorts );	  
	}

      linfo() << "Sorts OK" << endmsg;

      linfo() << "Classe " << type << " OK" << endmsg;
      
      tagClasse += '+';
      tagXP     += '+';
      tagComp   += '+';
      tagSorts  += '+';
      compteur++;
    }
  while( infoXML -> find(tagClasse) != infoXML -> end());

  // Accès au compétences diverses

  valeur  = infoXML -> operator[]( "Acces" );

  if ( !lireVectorUInt( valeur, &vecUInt ) )
    {
      error() << "Ne peut pas lire les accès" << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  else
    linfo() << "Accès : " << valeur << endmsg;

  setAcces( vecUInt );

  // PV et PP

  valeur = infoXML -> operator[]( "PV" );

  if ( !lireString( valeur, xp ) )
    {
      error() << "Ne peut pas lire le nombre de PV" << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  else
    linfo() << "Nbr de PV : " << valeur << endmsg;

  setPV( xp );

  valeur = infoXML -> operator[]( "PP" );

  if ( !lireString( valeur, xp ) )
    {
      error() << "Ne peut pas lire le nombre de PP" << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  linfo() << "Nbr de PP : " << valeur << endmsg;
  
  setPP( xp );
  
  // Dons

  valeur = infoXML -> operator[]( "Dons" );

  if( !lireVectorUInt( valeur, &vecUInt ) )
    {
      error() << "Ne peut pas lire les dons" << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  else
    linfo() << "Dons : " << valeur << endmsg;

  setDons( vecUInt );

  // Désavantages

  valeur = infoXML -> operator[]( "Desavantages" );

  if( !lireVectorUInt( valeur, &vecUInt ) )
    {
      error() << "Ne peut pas lire les désavantages" << endmsg;
      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  else
    linfo() << "Désavantages : " << valeur << endmsg;

  setDesavantages( vecUInt );

  // Compétences diverses

  valeur = infoXML -> operator[]( "Non-martiales" );

  if( !lireVectorUInt( valeur, &vecUInt ) )
    {
      error() << "Ne peut pas lire les compétences diverses" << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  else
    linfo() << "Compétences diverses : " << valeur << endmsg;

  setDiverses( vecUInt );

  // Compétences martiales

  valeur = infoXML -> operator[]( "Martiales" );

  if( ! lireVectorUInt( valeur, &vecUInt ) )
    {
      error() << "Ne peut pas lire les comptences martiales" << endmsg;

      func() << "Joueur::construitJoueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
  else
    linfo() << "Compétences martiales : " << valeur << endmsg;

  setMartiales( vecUInt );

  if (compteur != nbClasses)
    warning() << "Attention, problème avec le nombre de classes!" << endmsg
	      << nbClasses << " attendue(s), mais trouvée(s) " << compteur
	      << endmsg;

  if (nb_classes != J_classe.size() )
    warning() << "Petit problème de taille" << endmsg;

  func() << "Joueur::construitJoueur -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**
 * Est chargé de vérifier si la balise de l'élément de l'arbre DOM
 * passé en argument est bien la balise attendue.
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC permet d'afficher les messages de début et de fin de
 * méthode.
 *
 * @param[in] elDom pointeur sur l'élément DOM que lon veut vérifier.
 * @param[in] bal string avec laquelle comparer la balise de \c elDom.
 *
 * @return StatusCode, en cas d'erreur le message explicite le
 * problème de balisage.
 */
StatusCode Joueur::verifieBalise(const ElementDOM* elDom, const string& bal)
  const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::verifieBalise -> début" << endmsg;

  StatusCode sc;

  if ( elDom -> balise() != bal )
    sc = StatusCode( false, 0, -1, "La balise racine n'est pas <"
		     + bal + ">, mais <" + elDom -> balise() + '>' );

  func() << "Joueur::verifieBalise -> fin" << endmsg;
  return sc;
}

/**
 * Méthode qui est appelée par le constructeur pour faire la
 * vérification de la prochaine balise. On fait en fait appel à
 * verifieBalise, mais en cas d'échec on stoppe le programme.
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC permet d'afficher les messages de début et de fin de
 * méthode.
 *
 * @param[in] elDom pointeur sur l'élément DOM que l'on veut vérifier.
 * @param[in] bal string avec laquelle comparer la balise de \c elDom.
 */
void Joueur::faireVerificationBalise(const ElementDOM* elDom,
				     const string& bal) const
{
  StatusCode sc( verifieBalise( elDom, bal )  );
  if ( ! sc )
    {
      error() << sc.message() << endmsg;
      func() << "Joueur -> fin" << endmsg;
      /*Debug::*/depileNiveau();
      exit(1);
    }
}

/**
 * Récupère les données nécessaire à la construction d'une
 * Classe. Puisque le Joueur peut avoir plusieurs instances de Classe,
 * il est intéressant de regrouper tout ceci dans une méthode séparée.
 *
 * Le niveau de sortie est paramétré par Joueur::interne :\n
 * \e FUNC permet d'afficher les messages de début et de fin de
 * méthode.
 *
 * @param[in] elDom pointeur sur l'élément DOM qui contient les
 * informations sur une Classe.
 * @param[in] prefixe string contenant des "+", servant à identifier
 * les données des différentes instances de Classe à lire.
 * @param[in] parser pointeur sur le Parser, qui permet d'accéder aux
 * enfants et frères de \c elDom.
 * @param[out] infos référence sur le conteneur d'informations, qui
 * est rempli ici.
 */
void Joueur::lireClasse(const ElementDOM* elDom, const string& prefixe,
			const Parser *parser,
			map< string, string >& infos) const
{
  /*Debug::*/empileNiveau( &interne );
  func() << "Joueur::lireClasse -> " << endmsg;

  const ElementDOM *enfant;

  string balise( "Classe" );

  enfant = parser -> premierEnfant( elDom );
  faireVerificationBalise( enfant, balise );
  balise += prefixe;
  infos[ balise ] = enfant -> donnees();

  balise = "PV";
  faireVerificationBalise( enfant, balise );
  balise += prefixe;
  infos[ balise ] = enfant -> donnees();

  balise = "XP";
  faireVerificationBalise( enfant, balise );
  balise += prefixe;
  infos[ balise ] = enfant -> donnees();

  balise = "Competences";
  faireVerificationBalise( enfant, balise );
  balise += prefixe;
  infos[ balise ] = enfant -> donnees();

  balise = "Sorts";
  faireVerificationBalise( enfant, balise );
  balise += prefixe;
  infos[ balise ] = enfant -> donnees();

  func() << "Joueur::lireClasse -> " << endmsg;
  /*Debug::*/depileNiveau();
}
